From 4dd327ef5185bcc72bc551a608bdb47fd7c016ac Mon Sep 17 00:00:00 2001
From: Sean Keever <33592180+swkeever@users.noreply.github.com>
Date: Wed, 26 Aug 2026 18:22:47 -0400
Subject: [PATCH 1/6] feat(sdk): validate Python contract facade
---
.github/workflows/ci.yml | 11 +-
.gitignore | 1 +
README.md | 82 +-
features/contract/auth.feature | 8 +
features/contract/database.feature | 8 +
features/contract/locks.feature | 8 +
features/contract/realtime.feature | 8 +
features/contract/storage.feature | 8 +
features/contract_support.py | 146 +
features/environment.py | 38 +
features/steps/sdk_contract_steps.py | 192 +
openapi-python-client.yaml | 5 +
openapi/openapi.yaml | 16286 ++++++++++++++++
pyproject.toml | 18 +-
scripts/check_openapi.py | 54 +
scripts/generate_openapi.py | 61 +
src/volcano_sdk/__init__.py | 25 +-
src/volcano_sdk/_generated/__init__.py | 8 +
src/volcano_sdk/_generated/api/__init__.py | 1 +
.../_generated/api/anon_keys/__init__.py | 1 +
.../api/anon_keys/create_anon_key.py | 192 +
.../_generated/api/anon_keys/get_anon_key.py | 197 +
.../api/anon_keys/list_anon_keys.py | 297 +
.../api/anon_keys/regenerate_anon_key.py | 193 +
.../api/anon_keys/revoke_anon_key.py | 216 +
.../api/anon_keys/set_default_anon_key.py | 217 +
.../_generated/api/auth_admin/__init__.py | 1 +
.../api/auth_admin/ban_auth_user.py | 240 +
.../auth_admin/delete_all_user_sessions.py | 132 +
.../api/auth_admin/delete_auth_user.py | 127 +
.../api/auth_admin/delete_user_session.py | 139 +
.../api/auth_admin/get_auth_insights.py | 301 +
.../api/auth_admin/get_auth_user.py | 185 +
.../api/auth_admin/list_auth_users.py | 306 +
.../api/auth_admin/list_user_sessions.py | 365 +
.../api/auth_admin/unban_auth_user.py | 205 +
.../api/auth_configuration/__init__.py | 1 +
.../configure_auth_methods.py | 143 +
.../create_email_template.py | 246 +
.../delete_email_template.py | 211 +
.../api/auth_configuration/get_auth_config.py | 172 +
.../get_auth_hosted_page.py | 207 +
.../auth_configuration/get_auth_methods.py | 184 +
.../get_default_email_template.py | 177 +
.../get_default_email_templates.py | 158 +
.../auth_configuration/get_email_template.py | 191 +
.../get_hosted_login_options.py | 221 +
.../hosted_login_check_email.py | 231 +
.../list_email_templates.py | 180 +
.../render_default_managed_auth_page.py | 261 +
.../render_managed_auth_page.py | 207 +
.../auth_configuration/test_email_config.py | 292 +
.../auth_configuration/update_auth_config.py | 219 +
.../update_auth_hosted_page.py | 243 +
.../update_email_template.py | 239 +
.../_generated/api/authentication/__init__.py | 1 +
.../auth_cancel_email_change.py | 158 +
.../api/authentication/auth_confirm_email.py | 198 +
.../auth_confirm_email_change.py | 215 +
.../authentication/auth_convert_anonymous.py | 222 +
.../auth_delete_all_my_sessions.py | 166 +
.../authentication/auth_delete_my_session.py | 195 +
.../authentication/auth_forgot_password.py | 209 +
.../authentication/auth_get_my_sessions.py | 397 +
.../auth_get_password_policy.py | 181 +
.../api/authentication/auth_get_user.py | 166 +
.../authentication/auth_list_identities.py | 178 +
.../api/authentication/auth_list_methods.py | 174 +
.../api/authentication/auth_logout.py | 138 +
.../api/authentication/auth_promote_method.py | 221 +
.../api/authentication/auth_refresh.py | 235 +
.../auth_request_email_change.py | 226 +
.../auth_resend_confirmation.py | 210 +
.../api/authentication/auth_reset_password.py | 206 +
.../api/authentication/auth_signin.py | 222 +
.../api/authentication/auth_signup.py | 254 +
.../authentication/auth_signup_anonymous.py | 205 +
.../authentication/auth_unlink_identity.py | 206 +
.../api/authentication/auth_update_user.py | 211 +
.../api/database_branches/__init__.py | 1 +
.../create_database_branch.py | 285 +
.../delete_database_branch.py | 249 +
.../database_branches/get_database_branch.py | 225 +
.../list_database_branches.py | 224 +
.../reset_database_branch.py | 268 +
.../reset_database_branch_password.py | 244 +
.../update_database_branch.py | 267 +
.../api/database_queries/__init__.py | 1 +
.../query_database_branch_delete.py | 288 +
.../query_database_branch_insert.py | 292 +
.../query_database_branch_ping.py | 269 +
.../query_database_branch_select.py | 308 +
.../query_database_branch_update.py | 296 +
.../database_queries/query_database_delete.py | 259 +
.../database_queries/query_database_insert.py | 263 +
.../database_queries/query_database_ping.py | 240 +
.../database_queries/query_database_select.py | 279 +
.../database_queries/query_database_update.py | 267 +
.../_generated/api/databases/__init__.py | 1 +
.../api/databases/create_database.py | 232 +
.../api/databases/delete_database.py | 225 +
.../_generated/api/databases/get_database.py | 185 +
.../api/databases/get_database_stats.py | 292 +
.../databases/get_project_database_queries.py | 267 +
.../api/databases/list_database_regions.py | 167 +
.../api/databases/list_databases.py | 293 +
.../api/databases/list_postgres_versions.py | 167 +
.../api/databases/reset_database_password.py | 205 +
.../api/databases/update_database_type.py | 253 +
.../_generated/api/frontends/__init__.py | 1 +
.../api/frontends/create_frontend.py | 369 +
.../create_frontend_custom_domain.py | 278 +
.../api/frontends/delete_frontend.py | 244 +
.../delete_frontend_custom_domain.py | 217 +
.../_generated/api/frontends/get_frontend.py | 221 +
.../frontends/get_frontend_custom_domain.py | 234 +
.../frontends/get_frontend_usage_history.py | 283 +
.../frontends/list_frontend_deployments.py | 258 +
.../api/frontends/list_frontends.py | 329 +
.../frontends/list_project_custom_domains.py | 318 +
.../api/frontends/redeploy_frontend.py | 267 +
.../_generated/api/functions/__init__.py | 1 +
.../api/functions/create_function.py | 320 +
.../functions/create_function_scheduler.py | 225 +
.../api/functions/create_functions_batch.py | 271 +
.../api/functions/delete_function.py | 209 +
.../functions/delete_function_scheduler.py | 130 +
.../_generated/api/functions/get_function.py | 193 +
.../api/functions/get_function_scheduler.py | 198 +
.../api/functions/invoke_function.py | 357 +
.../functions/list_function_deployments.py | 230 +
.../api/functions/list_function_regions.py | 171 +
.../api/functions/list_function_runtimes.py | 166 +
.../api/functions/list_function_schedulers.py | 185 +
.../api/functions/list_functions.py | 301 +
.../api/functions/list_project_schedulers.py | 289 +
.../resolve_function_for_invocation.py | 264 +
.../api/functions/update_function.py | 220 +
.../functions/update_function_scheduler.py | 218 +
.../api/git_connections/__init__.py | 1 +
.../git_connections/delete_git_connection.py | 204 +
.../git_connections/git_connect_callback.py | 247 +
.../git_connections/list_git_connections.py | 172 +
.../list_git_installation_repositories.py | 237 +
.../git_connections/list_git_installations.py | 224 +
.../api/git_connections/start_git_connect.py | 250 +
.../_generated/api/locks/__init__.py | 1 +
.../api/locks/acquire_project_lock.py | 289 +
.../api/locks/force_release_project_lock.py | 254 +
.../_generated/api/locks/get_project_lock.py | 246 +
.../api/locks/release_project_lock.py | 252 +
.../api/locks/renew_project_lock.py | 285 +
.../_generated/api/logs/__init__.py | 1 +
.../api/logs/get_project_log_activity.py | 261 +
.../api/logs/search_project_logs.py | 265 +
.../api/logs/stream_project_logs.py | 345 +
.../api/o_auth_authentication/__init__.py | 1 +
.../auth_device_authorize.py | 266 +
.../auth_device_token.py | 209 +
.../auth_device_verify.py | 230 +
.../auth_link_o_auth_provider.py | 272 +
.../auth_list_o_auth_providers.py | 166 +
.../auth_o_auth_authorize.py | 181 +
.../auth_o_auth_callback.py | 260 +
.../auth_o_auth_exchange.py | 210 +
.../auth_platform_exchange.py | 202 +
.../auth_unlink_o_auth_provider.py | 203 +
.../call_o_auth_provider_api.py | 279 +
.../get_o_auth_provider_token.py | 200 +
.../refresh_o_auth_provider_token.py | 207 +
.../api/o_auth_configuration/__init__.py | 1 +
.../create_o_auth_config.py | 204 +
.../delete_o_auth_config.py | 142 +
.../o_auth_configuration/get_o_auth_config.py | 209 +
.../list_available_o_auth_providers.py | 180 +
.../list_o_auth_configs.py | 180 +
.../update_o_auth_config.py | 230 +
.../api/project_imports/__init__.py | 1 +
.../complete_import_connect.py | 322 +
.../delete_import_connection.py | 211 +
.../project_imports/get_project_import_run.py | 216 +
.../list_import_connections.py | 165 +
.../project_imports/list_import_sources.py | 261 +
.../preflight_project_import.py | 258 +
.../project_imports/start_import_connect.py | 246 +
.../project_imports/start_project_import.py | 284 +
.../_generated/api/projects/__init__.py | 1 +
.../api/projects/apply_project_config.py | 342 +
.../api/projects/connect_project_git.py | 271 +
.../_generated/api/projects/create_project.py | 205 +
.../_generated/api/projects/delete_project.py | 196 +
.../api/projects/delete_project_logo.py | 213 +
.../api/projects/disconnect_project_git.py | 197 +
.../_generated/api/projects/get_project.py | 180 +
.../api/projects/get_project_config.py | 251 +
.../projects/get_project_git_connection.py | 201 +
.../get_project_git_deploy_settings.py | 201 +
.../api/projects/get_project_health.py | 221 +
.../api/projects/get_project_logo.py | 196 +
.../api/projects/get_project_usage.py | 199 +
.../api/projects/list_deployments.py | 558 +
.../api/projects/list_project_deployments.py | 358 +
.../_generated/api/projects/list_projects.py | 299 +
.../api/projects/query_project_metrics.py | 251 +
.../set_project_git_production_branch.py | 284 +
.../projects/summarize_project_deployments.py | 288 +
.../_generated/api/projects/update_project.py | 221 +
.../update_project_git_deploy_settings.py | 280 +
.../api/projects/upload_project_logo.py | 248 +
.../_generated/api/realtime/__init__.py | 1 +
.../api/realtime/get_realtime_config.py | 195 +
.../api/realtime/get_realtime_stats.py | 188 +
.../api/realtime/update_realtime_config.py | 219 +
.../_generated/api/service_keys/__init__.py | 1 +
.../api/service_keys/create_service_key.py | 216 +
.../api/service_keys/delete_service_key.py | 129 +
.../api/service_keys/get_service_key.py | 197 +
.../api/service_keys/list_service_keys.py | 285 +
.../service_keys/regenerate_service_key.py | 201 +
.../_generated/api/storage_admin/__init__.py | 1 +
.../api/storage_admin/get_storage_stats.py | 180 +
.../list_storage_objects_admin.py | 299 +
.../api/storage_buckets/__init__.py | 1 +
.../storage_buckets/create_storage_bucket.py | 196 +
.../storage_buckets/delete_storage_bucket.py | 123 +
.../api/storage_buckets/get_storage_bucket.py | 189 +
.../storage_buckets/list_storage_buckets.py | 297 +
.../storage_buckets/update_storage_bucket.py | 205 +
.../api/storage_objects/__init__.py | 1 +
.../storage_objects/copy_storage_object.py | 203 +
.../storage_objects/delete_storage_object.py | 248 +
.../storage_objects/download_public_file.py | 302 +
.../download_storage_object.py | 279 +
.../storage_objects/list_storage_objects.py | 235 +
.../storage_objects/move_storage_object.py | 203 +
.../update_storage_object_visibility.py | 244 +
.../api/storage_objects/upload_part.py | 283 +
.../storage_objects/upload_storage_object.py | 352 +
.../api/storage_policies/__init__.py | 1 +
.../storage_policies/create_storage_policy.py | 205 +
.../storage_policies/delete_storage_policy.py | 130 +
.../storage_policies/list_storage_policies.py | 190 +
.../_generated/api/system/__init__.py | 1 +
.../_generated/api/system/health_check.py | 153 +
.../_generated/api/variables/__init__.py | 1 +
.../api/variables/create_variable.py | 212 +
.../api/variables/delete_variable.py | 201 +
.../_generated/api/variables/get_variable.py | 201 +
.../api/variables/list_variables.py | 285 +
.../api/variables/update_variable.py | 225 +
src/volcano_sdk/_generated/client.py | 271 +
src/volcano_sdk/_generated/errors.py | 14 +
src/volcano_sdk/_generated/models/__init__.py | 905 +
src/volcano_sdk/_generated/models/anon_key.py | 167 +
.../auth_cancel_email_change_response_200.py | 78 +
.../_generated/models/auth_config.py | 559 +
.../auth_config_allowed_email_domains_mode.py | 10 +
.../models/auth_confirm_email_body.py | 76 +
.../models/auth_confirm_email_change_body.py | 76 +
.../auth_confirm_email_change_response_200.py | 102 +
.../models/auth_confirm_email_response_200.py | 92 +
...auth_confirm_email_response_200_message.py | 10 +
.../models/auth_convert_anonymous_body.py | 110 +
...th_convert_anonymous_body_user_metadata.py | 65 +
.../auth_convert_anonymous_response_200.py | 93 +
.../models/auth_device_authorize_body.py | 76 +
.../models/auth_device_token_body.py | 98 +
.../auth_device_token_body_grant_type.py | 10 +
.../models/auth_device_verify_body.py | 100 +
.../models/auth_device_verify_body_action.py | 10 +
.../models/auth_device_verify_response_200.py | 87 +
.../models/auth_forgot_password_body.py | 76 +
.../auth_forgot_password_response_200.py | 78 +
.../auth_get_my_sessions_response_200.py | 190 +
.../models/auth_get_my_sessions_sort.py | 10 +
.../models/auth_get_my_sessions_status.py | 10 +
.../models/auth_get_user_response_200.py | 93 +
.../_generated/models/auth_hosted_page.py | 188 +
.../models/auth_hosted_page_defaults.py | 87 +
.../models/auth_hosted_page_response.py | 133 +
.../models/auth_hosted_page_runtime.py | 97 +
.../models/auth_identities_response.py | 94 +
.../_generated/models/auth_identity.py | 119 +
.../models/auth_insights_interval.py | 10 +
.../models/auth_insights_response.py | 128 +
.../models/auth_insights_series_point.py | 87 +
.../models/auth_insights_summary.py | 67 +
.../_generated/models/auth_insights_window.py | 87 +
.../auth_link_o_auth_provider_provider.py | 10 +
.../auth_link_o_auth_provider_response_200.py | 78 +
...auth_link_o_auth_provider_response_mode.py | 10 +
...auth_list_o_auth_providers_response_200.py | 100 +
...h_providers_response_200_providers_item.py | 118 +
.../_generated/models/auth_logout_body.py | 101 +
.../models/auth_logout_body_session_mode.py | 10 +
.../_generated/models/auth_method_summary.py | 173 +
.../models/auth_method_summary_type.py | 10 +
.../models/auth_methods_response.py | 94 +
.../models/auth_o_auth_authorize_provider.py | 10 +
.../auth_o_auth_authorize_response_mode.py | 10 +
.../models/auth_o_auth_callback_provider.py | 10 +
.../models/auth_o_auth_exchange_body.py | 84 +
.../_generated/models/auth_password_policy.py | 116 +
.../models/auth_platform_exchange_body.py | 76 +
.../_generated/models/auth_refresh_body.py | 101 +
.../models/auth_refresh_body_session_mode.py | 10 +
.../models/auth_request_email_change_body.py | 76 +
.../auth_request_email_change_response_200.py | 87 +
.../models/auth_resend_confirmation_body.py | 76 +
.../auth_resend_confirmation_response_200.py | 78 +
.../models/auth_reset_password_body.py | 85 +
.../auth_reset_password_response_200.py | 78 +
.../_generated/models/auth_session.py | 239 +
.../models/auth_session_provider.py | 10 +
.../_generated/models/auth_signin_body.py | 108 +
.../models/auth_signin_body_session_mode.py | 10 +
.../models/auth_signup_anonymous_body.py | 94 +
...uth_signup_anonymous_body_user_metadata.py | 69 +
.../_generated/models/auth_signup_body.py | 110 +
.../models/auth_signup_body_user_metadata.py | 65 +
.../_generated/models/auth_signup_response.py | 90 +
.../_generated/models/auth_token_response.py | 119 +
.../auth_unlink_o_auth_provider_provider.py | 10 +
.../models/auth_update_user_body.py | 105 +
.../auth_update_user_body_user_metadata.py | 68 +
.../models/auth_update_user_response_200.py | 93 +
.../_generated/models/auth_user.py | 276 +
.../models/auth_user_app_metadata.py | 66 +
.../_generated/models/auth_user_status.py | 10 +
.../models/auth_user_user_metadata.py | 66 +
.../_generated/models/ban_auth_user_body.py | 91 +
.../_generated/models/ban_user_response.py | 146 +
.../models/ban_user_response_status.py | 10 +
.../models/batch_function_deploy_failure.py | 128 +
...batch_function_deploy_failure_operation.py | 10 +
.../models/batch_function_deploy_response.py | 138 +
.../models/call_o_auth_provider_api_body.py | 126 +
.../call_o_auth_provider_api_body_body.py | 66 +
.../call_o_auth_provider_api_body_method.py | 10 +
.../call_o_auth_provider_api_provider.py | 10 +
.../call_o_auth_provider_api_response_200.py | 66 +
.../complete_upload_session_response.py | 94 +
.../models/configure_auth_methods_body.py | 118 +
..._auth_methods_body_oauth_providers_item.py | 87 +
.../models/connect_project_git_request.py | 137 +
.../_generated/models/create_anon_key_body.py | 112 +
.../create_anon_key_body_permissions_item.py | 10 +
.../models/create_database_branch_request.py | 88 +
.../models/create_database_request.py | 134 +
.../create_database_request_database_type.py | 10 +
.../create_database_request_pg_version.py | 10 +
.../models/create_database_request_region.py | 10 +
.../models/create_email_template_request.py | 109 +
...te_email_template_request_template_type.py | 10 +
.../_generated/models/create_frontend_body.py | 159 +
.../models/create_frontend_body_framework.py | 10 +
.../create_frontend_custom_domain_request.py | 92 +
.../_generated/models/create_function_body.py | 157 +
.../models/create_function_body_runtime.py | 10 +
.../create_function_scheduler_request.py | 139 +
...eate_function_scheduler_request_payload.py | 65 +
.../models/create_functions_batch_body.py | 125 +
.../models/create_o_auth_config_request.py | 128 +
.../create_o_auth_config_request_provider.py | 10 +
.../models/create_project_request.py | 109 +
.../models/create_service_key_body.py | 100 +
.../models/create_storage_bucket_request.py | 101 +
.../models/create_storage_policy_request.py | 98 +
...create_storage_policy_request_operation.py | 10 +
.../models/create_upload_session_request.py | 103 +
.../models/create_upload_session_response.py | 119 +
.../models/create_variable_request.py | 84 +
src/volcano_sdk/_generated/models/database.py | 247 +
.../_generated/models/database_branch.py | 235 +
.../_generated/models/database_branch_list.py | 94 +
.../models/database_branch_status.py | 10 +
.../models/database_branch_storage.py | 99 +
.../models/database_database_type.py | 10 +
.../models/database_delete_request.py | 103 +
.../models/database_insert_request.py | 93 +
.../models/database_insert_request_values.py | 69 +
.../models/database_query_filter.py | 142 +
.../models/database_query_filter_operator.py | 10 +
.../_generated/models/database_query_order.py | 96 +
.../database_query_performance_database.py | 88 +
.../models/database_query_performance_item.py | 156 +
.../database_query_performance_response.py | 94 +
.../models/database_query_result.py | 111 +
.../models/database_query_result_data_item.py | 65 +
.../models/database_select_request.py | 171 +
.../_generated/models/database_stats.py | 192 +
.../models/database_stats_granularity.py | 10 +
.../_generated/models/database_status.py | 10 +
.../models/database_update_request.py | 120 +
.../models/database_update_request_values.py | 69 +
.../delete_database_branch_response_202.py | 84 +
.../models/delete_database_response_202.py | 87 +
.../models/delete_email_template_type.py | 10 +
.../models/delete_o_auth_config_provider.py | 10 +
.../_generated/models/deployment_phase.py | 145 +
.../models/deployment_phase_name.py | 10 +
.../models/deployment_phase_status.py | 10 +
.../_generated/models/deployment_progress.py | 168 +
.../deployment_progress_current_phase.py | 10 +
.../_generated/models/deployment_reference.py | 81 +
.../models/device_authorization_response.py | 122 +
.../_generated/models/email_template.py | 186 +
.../models/email_template_template_type.py | 10 +
src/volcano_sdk/_generated/models/error.py | 86 +
src/volcano_sdk/_generated/models/frontend.py | 293 +
.../models/frontend_custom_domain_response.py | 203 +
...nd_custom_domain_response_domain_status.py | 10 +
...rontend_custom_domain_response_tls_mode.py | 10 +
...tom_domain_response_verification_status.py | 10 +
.../models/frontend_custom_domain_status.py | 10 +
.../frontend_custom_domain_tls_config.py | 108 +
.../frontend_custom_domain_tls_config_mode.py | 10 +
.../_generated/models/frontend_deployment.py | 304 +
.../frontend_deployment_deploy_source.py | 10 +
.../models/frontend_deployment_operation.py | 10 +
.../models/frontend_deployment_status.py | 10 +
.../models/frontend_domain_routing_record.py | 98 +
...ntend_domain_routing_record_record_type.py | 10 +
.../frontend_domain_verification_record.py | 92 +
.../_generated/models/frontend_framework.py | 10 +
.../_generated/models/frontend_status.py | 10 +
.../models/frontend_usage_daily_entry.py | 107 +
.../_generated/models/frontend_usage_data.py | 112 +
.../models/frontend_usage_history_response.py | 139 +
src/volcano_sdk/_generated/models/function.py | 270 +
.../_generated/models/function_deployment.py | 313 +
.../function_deployment_deploy_source.py | 10 +
.../models/function_deployment_operation.py | 10 +
.../models/function_deployment_status.py | 10 +
.../models/function_invocation_request.py | 106 +
.../function_invocation_request_payload.py | 79 +
.../models/function_invocation_response.py | 66 +
.../_generated/models/function_region.py | 92 +
.../models/function_runtime_deployment.py | 109 +
.../models/function_runtime_option.py | 108 +
.../models/function_runtimes_response.py | 94 +
.../_generated/models/function_scheduler.py | 338 +
.../function_scheduler_list_response.py | 146 +
.../models/function_scheduler_payload.py | 65 +
.../function_scheduler_schedule_kind.py | 10 +
.../_generated/models/function_status.py | 10 +
.../models/get_auth_methods_response_200.py | 158 +
...get_auth_methods_response_200_anonymous.py | 96 +
...uth_methods_response_200_email_password.py | 96 +
...thods_response_200_oauth_providers_item.py | 129 +
.../models/get_database_stats_granularity.py | 10 +
.../models/get_default_email_template_type.py | 10 +
...et_default_email_templates_response_200.py | 100 +
.../models/get_email_template_type.py | 10 +
.../models/get_o_auth_config_provider.py | 10 +
.../get_o_auth_provider_token_provider.py | 10 +
.../get_o_auth_provider_token_response_200.py | 96 +
.../models/get_project_config_format.py | 10 +
.../models/git_connect_start_response.py | 76 +
.../_generated/models/git_connection.py | 147 +
.../models/git_connections_response.py | 94 +
.../_generated/models/git_installation.py | 100 +
.../models/git_installations_response.py | 94 +
.../models/git_repositories_response.py | 94 +
.../_generated/models/git_repository.py | 100 +
.../models/hosted_auth_page_type.py | 10 +
.../hosted_login_email_check_request.py | 76 +
.../hosted_login_email_check_response.py | 78 +
.../models/hosted_login_options_response.py | 120 +
.../models/hosted_renderable_page_type.py | 10 +
.../models/import_connect_start_response.py | 76 +
.../_generated/models/import_connection.py | 205 +
.../models/import_connections_response.py | 94 +
.../_generated/models/import_provider.py | 10 +
.../_generated/models/import_source.py | 100 +
.../models/import_sources_response.py | 94 +
.../models/list_anon_keys_response_200.py | 137 +
.../models/list_auth_users_status.py | 10 +
...available_o_auth_providers_response_200.py | 100 +
...h_providers_response_200_providers_item.py | 102 +
...list_database_regions_response_200_item.py | 87 +
.../models/list_deployments_operation.py | 10 +
.../models/list_deployments_order.py | 10 +
.../models/list_deployments_resource_type.py | 10 +
.../models/list_deployments_status.py | 10 +
.../list_email_templates_response_200.py | 100 +
.../list_o_auth_configs_response_200.py | 100 +
...ist_postgres_versions_response_200_item.py | 105 +
.../list_project_deployments_resource_type.py | 10 +
...list_storage_objects_admin_response_200.py | 155 +
.../models/list_user_sessions_response_200.py | 190 +
.../models/list_user_sessions_sort.py | 10 +
.../models/list_user_sessions_status.py | 10 +
.../_generated/models/live_log_level.py | 10 +
.../_generated/models/log_activity_bucket.py | 116 +
.../models/log_activity_bucket_counts.py | 113 +
.../log_activity_bucket_counts_levels.py | 66 +
.../log_activity_bucket_counts_regions.py | 66 +
...log_activity_bucket_counts_resource_ids.py | 66 +
.../_generated/models/log_activity_request.py | 168 +
.../models/log_activity_response.py | 103 +
.../models/log_database_request_resource.py | 94 +
.../log_database_request_resource_type.py | 10 +
.../_generated/models/log_deployment.py | 105 +
.../models/log_deployment_request_selector.py | 81 +
.../_generated/models/log_deployment_stage.py | 10 +
.../_generated/models/log_event.py | 222 +
.../models/log_event_body_type_1.py | 65 +
.../models/log_frontend_request_resource.py | 117 +
.../log_frontend_request_resource_type.py | 10 +
.../models/log_function_request_resource.py | 117 +
.../log_function_request_resource_type.py | 10 +
.../_generated/models/log_resource.py | 105 +
.../_generated/models/log_resource_type.py | 10 +
.../_generated/models/log_search_event.py | 212 +
.../_generated/models/log_search_request.py | 177 +
.../_generated/models/log_search_response.py | 121 +
.../_generated/models/log_stream_request.py | 148 +
.../_generated/models/metric_usage_data.py | 146 +
.../_generated/models/o_auth_config.py | 201 +
.../models/o_auth_config_provider.py | 10 +
.../models/o_auth_error_response.py | 86 +
.../_generated/models/paginated_auth_users.py | 136 +
.../_generated/models/paginated_databases.py | 155 +
.../models/paginated_frontend_deployments.py | 136 +
.../_generated/models/paginated_frontends.py | 155 +
.../models/paginated_function_deployments.py | 136 +
.../_generated/models/paginated_functions.py | 155 +
.../paginated_project_custom_domains.py | 136 +
.../models/paginated_project_deployments.py | 159 +
.../_generated/models/paginated_projects.py | 218 +
.../models/paginated_projects_status.py | 10 +
.../models/paginated_service_keys.py | 155 +
.../models/paginated_storage_buckets.py | 140 +
.../_generated/models/paginated_variables.py | 155 +
.../models/platform_exchange_response.py | 109 +
src/volcano_sdk/_generated/models/project.py | 210 +
.../_generated/models/project_config.py | 288 +
.../models/project_config_apply_result.py | 170 +
.../project_config_apply_result_entry.py | 118 +
...roject_config_apply_result_entry_action.py | 10 +
.../models/project_config_apply_summary.py | 124 +
.../_generated/models/project_config_auth.py | 296 +
.../models/project_config_auth_cors.py | 93 +
.../models/project_config_auth_email.py | 132 +
.../models/project_config_auth_email_from.py | 69 +
...ect_config_auth_email_password_provider.py | 60 +
.../models/project_config_auth_email_smtp.py | 96 +
.../project_config_auth_email_verification.py | 70 +
.../project_config_auth_managed_pages.py | 107 +
.../models/project_config_auth_password.py | 96 +
.../project_config_auth_password_reset.py | 78 +
.../models/project_config_auth_providers.py | 105 +
.../models/project_config_auth_rate_limits.py | 88 +
.../models/project_config_auth_redirects.py | 93 +
.../models/project_config_auth_sessions.py | 69 +
.../models/project_config_auth_signup.py | 118 +
..._auth_signup_allowed_email_domains_mode.py | 10 +
.../models/project_config_auth_tokens.py | 88 +
.../models/project_config_bucket.py | 118 +
.../models/project_config_bucket_policy.py | 80 +
.../project_config_bucket_policy_operation.py | 10 +
.../models/project_config_custom_domain.py | 88 +
.../models/project_config_database.py | 109 +
.../project_config_database_database_type.py | 10 +
.../project_config_database_pg_version.py | 10 +
.../models/project_config_email_template.py | 78 +
.../models/project_config_email_templates.py | 136 +
.../models/project_config_frontend.py | 91 +
.../models/project_config_function.py | 103 +
.../models/project_config_hosted_page.py | 68 +
.../models/project_config_hosted_pages.py | 96 +
.../models/project_config_missing_resource.py | 90 +
.../project_config_missing_resource_type.py | 10 +
.../models/project_config_o_auth_provider.py | 116 +
...project_config_o_auth_provider_provider.py | 10 +
.../models/project_config_project.py | 85 +
.../models/project_config_realtime.py | 87 +
.../models/project_config_scheduler.py | 100 +
.../project_config_scheduler_payload.py | 65 +
.../models/project_config_skipped_resource.py | 98 +
.../project_config_skipped_resource_type.py | 10 +
.../models/project_config_validation_error.py | 94 +
...roject_config_validation_error_response.py | 103 +
.../models/project_config_variable.py | 66 +
.../models/project_config_version.py | 10 +
.../_generated/models/project_deployment.py | 231 +
.../project_deployment_deploy_source.py | 10 +
.../models/project_deployment_operation.py | 10 +
.../models/project_deployment_resource.py | 103 +
.../project_deployment_resource_type.py | 10 +
.../models/project_deployment_status.py | 10 +
.../models/project_deployment_summary.py | 132 +
.../models/project_frontend_custom_domain.py | 218 +
...project_frontend_custom_domain_frontend.py | 90 +
.../models/project_git_connection.py | 122 +
.../models/project_git_deploy_settings.py | 119 +
.../models/project_health_category.py | 10 +
.../_generated/models/project_health_check.py | 140 +
.../models/project_health_data_status.py | 10 +
.../models/project_health_evidence.py | 100 +
.../models/project_health_resource.py | 102 +
.../models/project_health_resource_type.py | 10 +
.../models/project_health_response.py | 176 +
.../_generated/models/project_health_scope.py | 84 +
.../models/project_health_status.py | 10 +
.../models/project_import_action.py | 110 +
.../models/project_import_action_code.py | 10 +
.../models/project_import_destination.py | 103 +
.../models/project_import_destination_mode.py | 10 +
.../models/project_import_disposition.py | 10 +
.../models/project_import_finding.py | 134 +
.../models/project_import_impact.py | 10 +
.../project_import_preflight_request.py | 123 +
.../models/project_import_readiness.py | 10 +
.../models/project_import_report.py | 230 +
.../models/project_import_resource.py | 109 +
.../models/project_import_resource_kind.py | 10 +
.../_generated/models/project_import_run.py | 190 +
.../models/project_import_run_status.py | 10 +
.../models/project_import_start_request.py | 126 +
.../models/project_import_summary.py | 116 +
.../models/project_import_target.py | 10 +
.../_generated/models/project_lock_lease.py | 75 +
.../models/project_lock_lease_request.py | 62 +
.../_generated/models/project_lock_state.py | 90 +
.../models/project_metrics_data_status.py | 10 +
.../models/project_metrics_dimensions.py | 83 +
...roject_metrics_dimensions_resource_type.py | 10 +
.../models/project_metrics_group_by.py | 10 +
.../models/project_metrics_metric.py | 10 +
.../models/project_metrics_query.py | 95 +
.../models/project_metrics_query_request.py | 90 +
.../models/project_metrics_query_response.py | 122 +
.../project_metrics_query_time_range.py | 64 +
...project_metrics_query_time_range_window.py | 10 +
.../models/project_metrics_result.py | 123 +
.../_generated/models/project_metrics_unit.py | 10 +
.../models/project_metrics_value.py | 74 +
.../models/project_metrics_window.py | 92 +
.../_generated/models/project_plan.py | 10 +
.../_generated/models/project_status.py | 10 +
.../models/project_usage_response.py | 145 +
.../_generated/models/realtime_config.py | 167 +
.../_generated/models/realtime_plan_limits.py | 115 +
.../_generated/models/realtime_stats.py | 132 +
.../refresh_o_auth_provider_token_provider.py | 10 +
...resh_o_auth_provider_token_response_200.py | 96 +
...render_default_managed_auth_page_action.py | 10 +
.../reset_database_password_response_200.py | 106 +
.../models/resolve_function_response.py | 96 +
.../_generated/models/resource_reference.py | 103 +
.../models/resource_reference_type.py | 10 +
.../_generated/models/schedule_request.py | 101 +
.../models/schedule_request_kind.py | 10 +
.../_generated/models/service_key.py | 183 +
...t_project_git_production_branch_request.py | 77 +
.../models/start_git_connect_provider.py | 10 +
.../_generated/models/storage_bucket.py | 223 +
.../_generated/models/storage_copy_request.py | 84 +
.../models/storage_list_response.py | 109 +
.../_generated/models/storage_move_request.py | 84 +
.../_generated/models/storage_object.py | 243 +
.../models/storage_object_metadata.py | 67 +
.../models/storage_object_with_bucket.py | 248 +
.../storage_object_with_bucket_metadata.py | 65 +
.../_generated/models/storage_policy.py | 166 +
.../models/storage_policy_operation.py | 10 +
.../_generated/models/storage_stats.py | 93 +
.../models/storage_visibility_request.py | 76 +
...arize_project_deployments_resource_type.py | 10 +
.../_generated/models/test_email_request.py | 115 +
.../_generated/models/test_email_response.py | 76 +
.../_generated/models/unban_user_response.py | 111 +
.../models/unban_user_response_status.py | 10 +
.../models/update_auth_config_request.py | 485 +
...nfig_request_allowed_email_domains_mode.py | 10 +
.../models/update_auth_hosted_page_request.py | 86 +
.../models/update_database_branch_request.py | 77 +
.../models/update_database_type_request.py | 83 +
...ate_database_type_request_database_type.py | 10 +
.../models/update_email_template_request.py | 96 +
.../models/update_email_template_type.py | 10 +
.../models/update_function_request.py | 78 +
.../update_function_scheduler_request.py | 147 +
...date_function_scheduler_request_payload.py | 65 +
.../models/update_o_auth_config_provider.py | 10 +
.../models/update_o_auth_config_request.py | 120 +
...ate_project_git_deploy_settings_request.py | 105 +
.../models/update_project_request.py | 107 +
.../models/update_realtime_config_request.py | 107 +
.../models/update_storage_bucket_request.py | 93 +
.../models/update_variable_request.py | 76 +
.../models/upload_project_logo_body.py | 101 +
.../_generated/models/upload_session_part.py | 97 +
.../models/upload_session_status_response.py | 234 +
.../upload_session_status_response_status.py | 10 +
.../upload_storage_object_files_body.py | 101 +
...upload_storage_object_x_upload_complete.py | 10 +
.../_generated/models/usage_data_point.py | 90 +
src/volcano_sdk/_generated/models/variable.py | 216 +
.../models/variable_deploy_source.py | 10 +
.../_generated/models/variable_status.py | 10 +
src/volcano_sdk/_generated/types.py | 53 +
src/volcano_sdk/_transport.py | 297 +
src/volcano_sdk/auth.py | 35 +
src/volcano_sdk/client.py | 65 +
src/volcano_sdk/database.py | 52 +
src/volcano_sdk/errors.py | 44 +
src/volcano_sdk/locks.py | 51 +
src/volcano_sdk/models.py | 19 +
src/volcano_sdk/realtime.py | 231 +
src/volcano_sdk/storage.py | 47 +
tests/fixtures/sdk-contract-dry-run.json | 19 +
tests/unit/test_contract_bindings.py | 85 +
tests/unit/test_errors.py | 91 +
tests/unit/test_facade.py | 134 +
tests/unit/test_generated_transport.py | 147 +
tests/unit/test_generation.py | 59 +
tests/unit/test_realtime.py | 136 +
tests/unit/test_state.py | 109 +
uv.lock | 712 +
722 files changed, 107915 insertions(+), 5 deletions(-)
create mode 100644 features/contract/auth.feature
create mode 100644 features/contract/database.feature
create mode 100644 features/contract/locks.feature
create mode 100644 features/contract/realtime.feature
create mode 100644 features/contract/storage.feature
create mode 100644 features/contract_support.py
create mode 100644 features/environment.py
create mode 100644 features/steps/sdk_contract_steps.py
create mode 100644 openapi-python-client.yaml
create mode 100644 openapi/openapi.yaml
create mode 100755 scripts/check_openapi.py
create mode 100755 scripts/generate_openapi.py
create mode 100644 src/volcano_sdk/_generated/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/anon_keys/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/anon_keys/create_anon_key.py
create mode 100644 src/volcano_sdk/_generated/api/anon_keys/get_anon_key.py
create mode 100644 src/volcano_sdk/_generated/api/anon_keys/list_anon_keys.py
create mode 100644 src/volcano_sdk/_generated/api/anon_keys/regenerate_anon_key.py
create mode 100644 src/volcano_sdk/_generated/api/anon_keys/revoke_anon_key.py
create mode 100644 src/volcano_sdk/_generated/api/anon_keys/set_default_anon_key.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/ban_auth_user.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/delete_all_user_sessions.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/delete_auth_user.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/delete_user_session.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/get_auth_insights.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/get_auth_user.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/list_auth_users.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/list_user_sessions.py
create mode 100644 src/volcano_sdk/_generated/api/auth_admin/unban_auth_user.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/configure_auth_methods.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/create_email_template.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/delete_email_template.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/get_auth_config.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/get_auth_hosted_page.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/get_auth_methods.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/get_default_email_template.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/get_default_email_templates.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/get_email_template.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/get_hosted_login_options.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/hosted_login_check_email.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/list_email_templates.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/render_default_managed_auth_page.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/render_managed_auth_page.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/test_email_config.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/update_auth_config.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/update_auth_hosted_page.py
create mode 100644 src/volcano_sdk/_generated/api/auth_configuration/update_email_template.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_cancel_email_change.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_confirm_email.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_confirm_email_change.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_convert_anonymous.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_delete_all_my_sessions.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_delete_my_session.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_forgot_password.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_get_my_sessions.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_get_password_policy.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_get_user.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_list_identities.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_list_methods.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_logout.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_promote_method.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_refresh.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_request_email_change.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_resend_confirmation.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_reset_password.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_signin.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_signup.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_signup_anonymous.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_unlink_identity.py
create mode 100644 src/volcano_sdk/_generated/api/authentication/auth_update_user.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/create_database_branch.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/delete_database_branch.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/get_database_branch.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/list_database_branches.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/reset_database_branch.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/reset_database_branch_password.py
create mode 100644 src/volcano_sdk/_generated/api/database_branches/update_database_branch.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_branch_delete.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_branch_insert.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_branch_ping.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_branch_select.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_branch_update.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_delete.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_insert.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_ping.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_select.py
create mode 100644 src/volcano_sdk/_generated/api/database_queries/query_database_update.py
create mode 100644 src/volcano_sdk/_generated/api/databases/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/databases/create_database.py
create mode 100644 src/volcano_sdk/_generated/api/databases/delete_database.py
create mode 100644 src/volcano_sdk/_generated/api/databases/get_database.py
create mode 100644 src/volcano_sdk/_generated/api/databases/get_database_stats.py
create mode 100644 src/volcano_sdk/_generated/api/databases/get_project_database_queries.py
create mode 100644 src/volcano_sdk/_generated/api/databases/list_database_regions.py
create mode 100644 src/volcano_sdk/_generated/api/databases/list_databases.py
create mode 100644 src/volcano_sdk/_generated/api/databases/list_postgres_versions.py
create mode 100644 src/volcano_sdk/_generated/api/databases/reset_database_password.py
create mode 100644 src/volcano_sdk/_generated/api/databases/update_database_type.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/create_frontend.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/create_frontend_custom_domain.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/delete_frontend.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/delete_frontend_custom_domain.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/get_frontend.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/get_frontend_custom_domain.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/get_frontend_usage_history.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/list_frontend_deployments.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/list_frontends.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/list_project_custom_domains.py
create mode 100644 src/volcano_sdk/_generated/api/frontends/redeploy_frontend.py
create mode 100644 src/volcano_sdk/_generated/api/functions/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/functions/create_function.py
create mode 100644 src/volcano_sdk/_generated/api/functions/create_function_scheduler.py
create mode 100644 src/volcano_sdk/_generated/api/functions/create_functions_batch.py
create mode 100644 src/volcano_sdk/_generated/api/functions/delete_function.py
create mode 100644 src/volcano_sdk/_generated/api/functions/delete_function_scheduler.py
create mode 100644 src/volcano_sdk/_generated/api/functions/get_function.py
create mode 100644 src/volcano_sdk/_generated/api/functions/get_function_scheduler.py
create mode 100644 src/volcano_sdk/_generated/api/functions/invoke_function.py
create mode 100644 src/volcano_sdk/_generated/api/functions/list_function_deployments.py
create mode 100644 src/volcano_sdk/_generated/api/functions/list_function_regions.py
create mode 100644 src/volcano_sdk/_generated/api/functions/list_function_runtimes.py
create mode 100644 src/volcano_sdk/_generated/api/functions/list_function_schedulers.py
create mode 100644 src/volcano_sdk/_generated/api/functions/list_functions.py
create mode 100644 src/volcano_sdk/_generated/api/functions/list_project_schedulers.py
create mode 100644 src/volcano_sdk/_generated/api/functions/resolve_function_for_invocation.py
create mode 100644 src/volcano_sdk/_generated/api/functions/update_function.py
create mode 100644 src/volcano_sdk/_generated/api/functions/update_function_scheduler.py
create mode 100644 src/volcano_sdk/_generated/api/git_connections/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/git_connections/delete_git_connection.py
create mode 100644 src/volcano_sdk/_generated/api/git_connections/git_connect_callback.py
create mode 100644 src/volcano_sdk/_generated/api/git_connections/list_git_connections.py
create mode 100644 src/volcano_sdk/_generated/api/git_connections/list_git_installation_repositories.py
create mode 100644 src/volcano_sdk/_generated/api/git_connections/list_git_installations.py
create mode 100644 src/volcano_sdk/_generated/api/git_connections/start_git_connect.py
create mode 100644 src/volcano_sdk/_generated/api/locks/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/locks/acquire_project_lock.py
create mode 100644 src/volcano_sdk/_generated/api/locks/force_release_project_lock.py
create mode 100644 src/volcano_sdk/_generated/api/locks/get_project_lock.py
create mode 100644 src/volcano_sdk/_generated/api/locks/release_project_lock.py
create mode 100644 src/volcano_sdk/_generated/api/locks/renew_project_lock.py
create mode 100644 src/volcano_sdk/_generated/api/logs/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/logs/get_project_log_activity.py
create mode 100644 src/volcano_sdk/_generated/api/logs/search_project_logs.py
create mode 100644 src/volcano_sdk/_generated/api/logs/stream_project_logs.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_authorize.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_token.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_verify.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_link_o_auth_provider.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_list_o_auth_providers.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_authorize.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_callback.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_exchange.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_platform_exchange.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/auth_unlink_o_auth_provider.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/call_o_auth_provider_api.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/get_o_auth_provider_token.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_authentication/refresh_o_auth_provider_token.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_configuration/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_configuration/create_o_auth_config.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_configuration/delete_o_auth_config.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_configuration/get_o_auth_config.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_configuration/list_available_o_auth_providers.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_configuration/list_o_auth_configs.py
create mode 100644 src/volcano_sdk/_generated/api/o_auth_configuration/update_o_auth_config.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/complete_import_connect.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/delete_import_connection.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/get_project_import_run.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/list_import_connections.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/list_import_sources.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/preflight_project_import.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/start_import_connect.py
create mode 100644 src/volcano_sdk/_generated/api/project_imports/start_project_import.py
create mode 100644 src/volcano_sdk/_generated/api/projects/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/projects/apply_project_config.py
create mode 100644 src/volcano_sdk/_generated/api/projects/connect_project_git.py
create mode 100644 src/volcano_sdk/_generated/api/projects/create_project.py
create mode 100644 src/volcano_sdk/_generated/api/projects/delete_project.py
create mode 100644 src/volcano_sdk/_generated/api/projects/delete_project_logo.py
create mode 100644 src/volcano_sdk/_generated/api/projects/disconnect_project_git.py
create mode 100644 src/volcano_sdk/_generated/api/projects/get_project.py
create mode 100644 src/volcano_sdk/_generated/api/projects/get_project_config.py
create mode 100644 src/volcano_sdk/_generated/api/projects/get_project_git_connection.py
create mode 100644 src/volcano_sdk/_generated/api/projects/get_project_git_deploy_settings.py
create mode 100644 src/volcano_sdk/_generated/api/projects/get_project_health.py
create mode 100644 src/volcano_sdk/_generated/api/projects/get_project_logo.py
create mode 100644 src/volcano_sdk/_generated/api/projects/get_project_usage.py
create mode 100644 src/volcano_sdk/_generated/api/projects/list_deployments.py
create mode 100644 src/volcano_sdk/_generated/api/projects/list_project_deployments.py
create mode 100644 src/volcano_sdk/_generated/api/projects/list_projects.py
create mode 100644 src/volcano_sdk/_generated/api/projects/query_project_metrics.py
create mode 100644 src/volcano_sdk/_generated/api/projects/set_project_git_production_branch.py
create mode 100644 src/volcano_sdk/_generated/api/projects/summarize_project_deployments.py
create mode 100644 src/volcano_sdk/_generated/api/projects/update_project.py
create mode 100644 src/volcano_sdk/_generated/api/projects/update_project_git_deploy_settings.py
create mode 100644 src/volcano_sdk/_generated/api/projects/upload_project_logo.py
create mode 100644 src/volcano_sdk/_generated/api/realtime/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/realtime/get_realtime_config.py
create mode 100644 src/volcano_sdk/_generated/api/realtime/get_realtime_stats.py
create mode 100644 src/volcano_sdk/_generated/api/realtime/update_realtime_config.py
create mode 100644 src/volcano_sdk/_generated/api/service_keys/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/service_keys/create_service_key.py
create mode 100644 src/volcano_sdk/_generated/api/service_keys/delete_service_key.py
create mode 100644 src/volcano_sdk/_generated/api/service_keys/get_service_key.py
create mode 100644 src/volcano_sdk/_generated/api/service_keys/list_service_keys.py
create mode 100644 src/volcano_sdk/_generated/api/service_keys/regenerate_service_key.py
create mode 100644 src/volcano_sdk/_generated/api/storage_admin/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/storage_admin/get_storage_stats.py
create mode 100644 src/volcano_sdk/_generated/api/storage_admin/list_storage_objects_admin.py
create mode 100644 src/volcano_sdk/_generated/api/storage_buckets/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/storage_buckets/create_storage_bucket.py
create mode 100644 src/volcano_sdk/_generated/api/storage_buckets/delete_storage_bucket.py
create mode 100644 src/volcano_sdk/_generated/api/storage_buckets/get_storage_bucket.py
create mode 100644 src/volcano_sdk/_generated/api/storage_buckets/list_storage_buckets.py
create mode 100644 src/volcano_sdk/_generated/api/storage_buckets/update_storage_bucket.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/copy_storage_object.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/delete_storage_object.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/download_public_file.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/download_storage_object.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/list_storage_objects.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/move_storage_object.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/update_storage_object_visibility.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/upload_part.py
create mode 100644 src/volcano_sdk/_generated/api/storage_objects/upload_storage_object.py
create mode 100644 src/volcano_sdk/_generated/api/storage_policies/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/storage_policies/create_storage_policy.py
create mode 100644 src/volcano_sdk/_generated/api/storage_policies/delete_storage_policy.py
create mode 100644 src/volcano_sdk/_generated/api/storage_policies/list_storage_policies.py
create mode 100644 src/volcano_sdk/_generated/api/system/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/system/health_check.py
create mode 100644 src/volcano_sdk/_generated/api/variables/__init__.py
create mode 100644 src/volcano_sdk/_generated/api/variables/create_variable.py
create mode 100644 src/volcano_sdk/_generated/api/variables/delete_variable.py
create mode 100644 src/volcano_sdk/_generated/api/variables/get_variable.py
create mode 100644 src/volcano_sdk/_generated/api/variables/list_variables.py
create mode 100644 src/volcano_sdk/_generated/api/variables/update_variable.py
create mode 100644 src/volcano_sdk/_generated/client.py
create mode 100644 src/volcano_sdk/_generated/errors.py
create mode 100644 src/volcano_sdk/_generated/models/__init__.py
create mode 100644 src/volcano_sdk/_generated/models/anon_key.py
create mode 100644 src/volcano_sdk/_generated/models/auth_cancel_email_change_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_config.py
create mode 100644 src/volcano_sdk/_generated/models/auth_config_allowed_email_domains_mode.py
create mode 100644 src/volcano_sdk/_generated/models/auth_confirm_email_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_confirm_email_change_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_confirm_email_change_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_confirm_email_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_confirm_email_response_200_message.py
create mode 100644 src/volcano_sdk/_generated/models/auth_convert_anonymous_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_convert_anonymous_body_user_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/auth_convert_anonymous_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_device_authorize_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_device_token_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_device_token_body_grant_type.py
create mode 100644 src/volcano_sdk/_generated/models/auth_device_verify_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_device_verify_body_action.py
create mode 100644 src/volcano_sdk/_generated/models/auth_device_verify_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_forgot_password_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_forgot_password_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_get_my_sessions_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_get_my_sessions_sort.py
create mode 100644 src/volcano_sdk/_generated/models/auth_get_my_sessions_status.py
create mode 100644 src/volcano_sdk/_generated/models/auth_get_user_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_hosted_page.py
create mode 100644 src/volcano_sdk/_generated/models/auth_hosted_page_defaults.py
create mode 100644 src/volcano_sdk/_generated/models/auth_hosted_page_response.py
create mode 100644 src/volcano_sdk/_generated/models/auth_hosted_page_runtime.py
create mode 100644 src/volcano_sdk/_generated/models/auth_identities_response.py
create mode 100644 src/volcano_sdk/_generated/models/auth_identity.py
create mode 100644 src/volcano_sdk/_generated/models/auth_insights_interval.py
create mode 100644 src/volcano_sdk/_generated/models/auth_insights_response.py
create mode 100644 src/volcano_sdk/_generated/models/auth_insights_series_point.py
create mode 100644 src/volcano_sdk/_generated/models/auth_insights_summary.py
create mode 100644 src/volcano_sdk/_generated/models/auth_insights_window.py
create mode 100644 src/volcano_sdk/_generated/models/auth_link_o_auth_provider_provider.py
create mode 100644 src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_mode.py
create mode 100644 src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200_providers_item.py
create mode 100644 src/volcano_sdk/_generated/models/auth_logout_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_logout_body_session_mode.py
create mode 100644 src/volcano_sdk/_generated/models/auth_method_summary.py
create mode 100644 src/volcano_sdk/_generated/models/auth_method_summary_type.py
create mode 100644 src/volcano_sdk/_generated/models/auth_methods_response.py
create mode 100644 src/volcano_sdk/_generated/models/auth_o_auth_authorize_provider.py
create mode 100644 src/volcano_sdk/_generated/models/auth_o_auth_authorize_response_mode.py
create mode 100644 src/volcano_sdk/_generated/models/auth_o_auth_callback_provider.py
create mode 100644 src/volcano_sdk/_generated/models/auth_o_auth_exchange_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_password_policy.py
create mode 100644 src/volcano_sdk/_generated/models/auth_platform_exchange_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_refresh_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_refresh_body_session_mode.py
create mode 100644 src/volcano_sdk/_generated/models/auth_request_email_change_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_request_email_change_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_resend_confirmation_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_resend_confirmation_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_reset_password_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_reset_password_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_session.py
create mode 100644 src/volcano_sdk/_generated/models/auth_session_provider.py
create mode 100644 src/volcano_sdk/_generated/models/auth_signin_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_signin_body_session_mode.py
create mode 100644 src/volcano_sdk/_generated/models/auth_signup_anonymous_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_signup_anonymous_body_user_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/auth_signup_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_signup_body_user_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/auth_signup_response.py
create mode 100644 src/volcano_sdk/_generated/models/auth_token_response.py
create mode 100644 src/volcano_sdk/_generated/models/auth_unlink_o_auth_provider_provider.py
create mode 100644 src/volcano_sdk/_generated/models/auth_update_user_body.py
create mode 100644 src/volcano_sdk/_generated/models/auth_update_user_body_user_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/auth_update_user_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/auth_user.py
create mode 100644 src/volcano_sdk/_generated/models/auth_user_app_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/auth_user_status.py
create mode 100644 src/volcano_sdk/_generated/models/auth_user_user_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/ban_auth_user_body.py
create mode 100644 src/volcano_sdk/_generated/models/ban_user_response.py
create mode 100644 src/volcano_sdk/_generated/models/ban_user_response_status.py
create mode 100644 src/volcano_sdk/_generated/models/batch_function_deploy_failure.py
create mode 100644 src/volcano_sdk/_generated/models/batch_function_deploy_failure_operation.py
create mode 100644 src/volcano_sdk/_generated/models/batch_function_deploy_response.py
create mode 100644 src/volcano_sdk/_generated/models/call_o_auth_provider_api_body.py
create mode 100644 src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_body.py
create mode 100644 src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_method.py
create mode 100644 src/volcano_sdk/_generated/models/call_o_auth_provider_api_provider.py
create mode 100644 src/volcano_sdk/_generated/models/call_o_auth_provider_api_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/complete_upload_session_response.py
create mode 100644 src/volcano_sdk/_generated/models/configure_auth_methods_body.py
create mode 100644 src/volcano_sdk/_generated/models/configure_auth_methods_body_oauth_providers_item.py
create mode 100644 src/volcano_sdk/_generated/models/connect_project_git_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_anon_key_body.py
create mode 100644 src/volcano_sdk/_generated/models/create_anon_key_body_permissions_item.py
create mode 100644 src/volcano_sdk/_generated/models/create_database_branch_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_database_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_database_request_database_type.py
create mode 100644 src/volcano_sdk/_generated/models/create_database_request_pg_version.py
create mode 100644 src/volcano_sdk/_generated/models/create_database_request_region.py
create mode 100644 src/volcano_sdk/_generated/models/create_email_template_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_email_template_request_template_type.py
create mode 100644 src/volcano_sdk/_generated/models/create_frontend_body.py
create mode 100644 src/volcano_sdk/_generated/models/create_frontend_body_framework.py
create mode 100644 src/volcano_sdk/_generated/models/create_frontend_custom_domain_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_function_body.py
create mode 100644 src/volcano_sdk/_generated/models/create_function_body_runtime.py
create mode 100644 src/volcano_sdk/_generated/models/create_function_scheduler_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_function_scheduler_request_payload.py
create mode 100644 src/volcano_sdk/_generated/models/create_functions_batch_body.py
create mode 100644 src/volcano_sdk/_generated/models/create_o_auth_config_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_o_auth_config_request_provider.py
create mode 100644 src/volcano_sdk/_generated/models/create_project_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_service_key_body.py
create mode 100644 src/volcano_sdk/_generated/models/create_storage_bucket_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_storage_policy_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_storage_policy_request_operation.py
create mode 100644 src/volcano_sdk/_generated/models/create_upload_session_request.py
create mode 100644 src/volcano_sdk/_generated/models/create_upload_session_response.py
create mode 100644 src/volcano_sdk/_generated/models/create_variable_request.py
create mode 100644 src/volcano_sdk/_generated/models/database.py
create mode 100644 src/volcano_sdk/_generated/models/database_branch.py
create mode 100644 src/volcano_sdk/_generated/models/database_branch_list.py
create mode 100644 src/volcano_sdk/_generated/models/database_branch_status.py
create mode 100644 src/volcano_sdk/_generated/models/database_branch_storage.py
create mode 100644 src/volcano_sdk/_generated/models/database_database_type.py
create mode 100644 src/volcano_sdk/_generated/models/database_delete_request.py
create mode 100644 src/volcano_sdk/_generated/models/database_insert_request.py
create mode 100644 src/volcano_sdk/_generated/models/database_insert_request_values.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_filter.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_filter_operator.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_order.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_performance_database.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_performance_item.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_performance_response.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_result.py
create mode 100644 src/volcano_sdk/_generated/models/database_query_result_data_item.py
create mode 100644 src/volcano_sdk/_generated/models/database_select_request.py
create mode 100644 src/volcano_sdk/_generated/models/database_stats.py
create mode 100644 src/volcano_sdk/_generated/models/database_stats_granularity.py
create mode 100644 src/volcano_sdk/_generated/models/database_status.py
create mode 100644 src/volcano_sdk/_generated/models/database_update_request.py
create mode 100644 src/volcano_sdk/_generated/models/database_update_request_values.py
create mode 100644 src/volcano_sdk/_generated/models/delete_database_branch_response_202.py
create mode 100644 src/volcano_sdk/_generated/models/delete_database_response_202.py
create mode 100644 src/volcano_sdk/_generated/models/delete_email_template_type.py
create mode 100644 src/volcano_sdk/_generated/models/delete_o_auth_config_provider.py
create mode 100644 src/volcano_sdk/_generated/models/deployment_phase.py
create mode 100644 src/volcano_sdk/_generated/models/deployment_phase_name.py
create mode 100644 src/volcano_sdk/_generated/models/deployment_phase_status.py
create mode 100644 src/volcano_sdk/_generated/models/deployment_progress.py
create mode 100644 src/volcano_sdk/_generated/models/deployment_progress_current_phase.py
create mode 100644 src/volcano_sdk/_generated/models/deployment_reference.py
create mode 100644 src/volcano_sdk/_generated/models/device_authorization_response.py
create mode 100644 src/volcano_sdk/_generated/models/email_template.py
create mode 100644 src/volcano_sdk/_generated/models/email_template_template_type.py
create mode 100644 src/volcano_sdk/_generated/models/error.py
create mode 100644 src/volcano_sdk/_generated/models/frontend.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_custom_domain_response.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_custom_domain_response_domain_status.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_custom_domain_response_tls_mode.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_custom_domain_response_verification_status.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_custom_domain_status.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config_mode.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_deployment.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_deployment_deploy_source.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_deployment_operation.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_deployment_status.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_domain_routing_record.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_domain_routing_record_record_type.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_domain_verification_record.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_framework.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_status.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_usage_daily_entry.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_usage_data.py
create mode 100644 src/volcano_sdk/_generated/models/frontend_usage_history_response.py
create mode 100644 src/volcano_sdk/_generated/models/function.py
create mode 100644 src/volcano_sdk/_generated/models/function_deployment.py
create mode 100644 src/volcano_sdk/_generated/models/function_deployment_deploy_source.py
create mode 100644 src/volcano_sdk/_generated/models/function_deployment_operation.py
create mode 100644 src/volcano_sdk/_generated/models/function_deployment_status.py
create mode 100644 src/volcano_sdk/_generated/models/function_invocation_request.py
create mode 100644 src/volcano_sdk/_generated/models/function_invocation_request_payload.py
create mode 100644 src/volcano_sdk/_generated/models/function_invocation_response.py
create mode 100644 src/volcano_sdk/_generated/models/function_region.py
create mode 100644 src/volcano_sdk/_generated/models/function_runtime_deployment.py
create mode 100644 src/volcano_sdk/_generated/models/function_runtime_option.py
create mode 100644 src/volcano_sdk/_generated/models/function_runtimes_response.py
create mode 100644 src/volcano_sdk/_generated/models/function_scheduler.py
create mode 100644 src/volcano_sdk/_generated/models/function_scheduler_list_response.py
create mode 100644 src/volcano_sdk/_generated/models/function_scheduler_payload.py
create mode 100644 src/volcano_sdk/_generated/models/function_scheduler_schedule_kind.py
create mode 100644 src/volcano_sdk/_generated/models/function_status.py
create mode 100644 src/volcano_sdk/_generated/models/get_auth_methods_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/get_auth_methods_response_200_anonymous.py
create mode 100644 src/volcano_sdk/_generated/models/get_auth_methods_response_200_email_password.py
create mode 100644 src/volcano_sdk/_generated/models/get_auth_methods_response_200_oauth_providers_item.py
create mode 100644 src/volcano_sdk/_generated/models/get_database_stats_granularity.py
create mode 100644 src/volcano_sdk/_generated/models/get_default_email_template_type.py
create mode 100644 src/volcano_sdk/_generated/models/get_default_email_templates_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/get_email_template_type.py
create mode 100644 src/volcano_sdk/_generated/models/get_o_auth_config_provider.py
create mode 100644 src/volcano_sdk/_generated/models/get_o_auth_provider_token_provider.py
create mode 100644 src/volcano_sdk/_generated/models/get_o_auth_provider_token_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/get_project_config_format.py
create mode 100644 src/volcano_sdk/_generated/models/git_connect_start_response.py
create mode 100644 src/volcano_sdk/_generated/models/git_connection.py
create mode 100644 src/volcano_sdk/_generated/models/git_connections_response.py
create mode 100644 src/volcano_sdk/_generated/models/git_installation.py
create mode 100644 src/volcano_sdk/_generated/models/git_installations_response.py
create mode 100644 src/volcano_sdk/_generated/models/git_repositories_response.py
create mode 100644 src/volcano_sdk/_generated/models/git_repository.py
create mode 100644 src/volcano_sdk/_generated/models/hosted_auth_page_type.py
create mode 100644 src/volcano_sdk/_generated/models/hosted_login_email_check_request.py
create mode 100644 src/volcano_sdk/_generated/models/hosted_login_email_check_response.py
create mode 100644 src/volcano_sdk/_generated/models/hosted_login_options_response.py
create mode 100644 src/volcano_sdk/_generated/models/hosted_renderable_page_type.py
create mode 100644 src/volcano_sdk/_generated/models/import_connect_start_response.py
create mode 100644 src/volcano_sdk/_generated/models/import_connection.py
create mode 100644 src/volcano_sdk/_generated/models/import_connections_response.py
create mode 100644 src/volcano_sdk/_generated/models/import_provider.py
create mode 100644 src/volcano_sdk/_generated/models/import_source.py
create mode 100644 src/volcano_sdk/_generated/models/import_sources_response.py
create mode 100644 src/volcano_sdk/_generated/models/list_anon_keys_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/list_auth_users_status.py
create mode 100644 src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200_providers_item.py
create mode 100644 src/volcano_sdk/_generated/models/list_database_regions_response_200_item.py
create mode 100644 src/volcano_sdk/_generated/models/list_deployments_operation.py
create mode 100644 src/volcano_sdk/_generated/models/list_deployments_order.py
create mode 100644 src/volcano_sdk/_generated/models/list_deployments_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/list_deployments_status.py
create mode 100644 src/volcano_sdk/_generated/models/list_email_templates_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/list_o_auth_configs_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/list_postgres_versions_response_200_item.py
create mode 100644 src/volcano_sdk/_generated/models/list_project_deployments_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/list_storage_objects_admin_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/list_user_sessions_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/list_user_sessions_sort.py
create mode 100644 src/volcano_sdk/_generated/models/list_user_sessions_status.py
create mode 100644 src/volcano_sdk/_generated/models/live_log_level.py
create mode 100644 src/volcano_sdk/_generated/models/log_activity_bucket.py
create mode 100644 src/volcano_sdk/_generated/models/log_activity_bucket_counts.py
create mode 100644 src/volcano_sdk/_generated/models/log_activity_bucket_counts_levels.py
create mode 100644 src/volcano_sdk/_generated/models/log_activity_bucket_counts_regions.py
create mode 100644 src/volcano_sdk/_generated/models/log_activity_bucket_counts_resource_ids.py
create mode 100644 src/volcano_sdk/_generated/models/log_activity_request.py
create mode 100644 src/volcano_sdk/_generated/models/log_activity_response.py
create mode 100644 src/volcano_sdk/_generated/models/log_database_request_resource.py
create mode 100644 src/volcano_sdk/_generated/models/log_database_request_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/log_deployment.py
create mode 100644 src/volcano_sdk/_generated/models/log_deployment_request_selector.py
create mode 100644 src/volcano_sdk/_generated/models/log_deployment_stage.py
create mode 100644 src/volcano_sdk/_generated/models/log_event.py
create mode 100644 src/volcano_sdk/_generated/models/log_event_body_type_1.py
create mode 100644 src/volcano_sdk/_generated/models/log_frontend_request_resource.py
create mode 100644 src/volcano_sdk/_generated/models/log_frontend_request_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/log_function_request_resource.py
create mode 100644 src/volcano_sdk/_generated/models/log_function_request_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/log_resource.py
create mode 100644 src/volcano_sdk/_generated/models/log_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/log_search_event.py
create mode 100644 src/volcano_sdk/_generated/models/log_search_request.py
create mode 100644 src/volcano_sdk/_generated/models/log_search_response.py
create mode 100644 src/volcano_sdk/_generated/models/log_stream_request.py
create mode 100644 src/volcano_sdk/_generated/models/metric_usage_data.py
create mode 100644 src/volcano_sdk/_generated/models/o_auth_config.py
create mode 100644 src/volcano_sdk/_generated/models/o_auth_config_provider.py
create mode 100644 src/volcano_sdk/_generated/models/o_auth_error_response.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_auth_users.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_databases.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_frontend_deployments.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_frontends.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_function_deployments.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_functions.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_project_custom_domains.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_project_deployments.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_projects.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_projects_status.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_service_keys.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_storage_buckets.py
create mode 100644 src/volcano_sdk/_generated/models/paginated_variables.py
create mode 100644 src/volcano_sdk/_generated/models/platform_exchange_response.py
create mode 100644 src/volcano_sdk/_generated/models/project.py
create mode 100644 src/volcano_sdk/_generated/models/project_config.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_apply_result.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_apply_result_entry.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_apply_result_entry_action.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_apply_summary.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_cors.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_email.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_email_from.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_email_password_provider.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_email_smtp.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_email_verification.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_managed_pages.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_password.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_password_reset.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_providers.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_rate_limits.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_redirects.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_sessions.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_signup.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_signup_allowed_email_domains_mode.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_auth_tokens.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_bucket.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_bucket_policy.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_bucket_policy_operation.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_custom_domain.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_database.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_database_database_type.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_database_pg_version.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_email_template.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_email_templates.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_frontend.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_function.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_hosted_page.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_hosted_pages.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_missing_resource.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_missing_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_o_auth_provider.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_o_auth_provider_provider.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_project.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_realtime.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_scheduler.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_scheduler_payload.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_skipped_resource.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_skipped_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_validation_error.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_validation_error_response.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_variable.py
create mode 100644 src/volcano_sdk/_generated/models/project_config_version.py
create mode 100644 src/volcano_sdk/_generated/models/project_deployment.py
create mode 100644 src/volcano_sdk/_generated/models/project_deployment_deploy_source.py
create mode 100644 src/volcano_sdk/_generated/models/project_deployment_operation.py
create mode 100644 src/volcano_sdk/_generated/models/project_deployment_resource.py
create mode 100644 src/volcano_sdk/_generated/models/project_deployment_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/project_deployment_status.py
create mode 100644 src/volcano_sdk/_generated/models/project_deployment_summary.py
create mode 100644 src/volcano_sdk/_generated/models/project_frontend_custom_domain.py
create mode 100644 src/volcano_sdk/_generated/models/project_frontend_custom_domain_frontend.py
create mode 100644 src/volcano_sdk/_generated/models/project_git_connection.py
create mode 100644 src/volcano_sdk/_generated/models/project_git_deploy_settings.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_category.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_check.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_data_status.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_evidence.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_resource.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_response.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_scope.py
create mode 100644 src/volcano_sdk/_generated/models/project_health_status.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_action.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_action_code.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_destination.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_destination_mode.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_disposition.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_finding.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_impact.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_preflight_request.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_readiness.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_report.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_resource.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_resource_kind.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_run.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_run_status.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_start_request.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_summary.py
create mode 100644 src/volcano_sdk/_generated/models/project_import_target.py
create mode 100644 src/volcano_sdk/_generated/models/project_lock_lease.py
create mode 100644 src/volcano_sdk/_generated/models/project_lock_lease_request.py
create mode 100644 src/volcano_sdk/_generated/models/project_lock_state.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_data_status.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_dimensions.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_dimensions_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_group_by.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_metric.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_query.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_query_request.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_query_response.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_query_time_range.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_query_time_range_window.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_result.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_unit.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_value.py
create mode 100644 src/volcano_sdk/_generated/models/project_metrics_window.py
create mode 100644 src/volcano_sdk/_generated/models/project_plan.py
create mode 100644 src/volcano_sdk/_generated/models/project_status.py
create mode 100644 src/volcano_sdk/_generated/models/project_usage_response.py
create mode 100644 src/volcano_sdk/_generated/models/realtime_config.py
create mode 100644 src/volcano_sdk/_generated/models/realtime_plan_limits.py
create mode 100644 src/volcano_sdk/_generated/models/realtime_stats.py
create mode 100644 src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_provider.py
create mode 100644 src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/render_default_managed_auth_page_action.py
create mode 100644 src/volcano_sdk/_generated/models/reset_database_password_response_200.py
create mode 100644 src/volcano_sdk/_generated/models/resolve_function_response.py
create mode 100644 src/volcano_sdk/_generated/models/resource_reference.py
create mode 100644 src/volcano_sdk/_generated/models/resource_reference_type.py
create mode 100644 src/volcano_sdk/_generated/models/schedule_request.py
create mode 100644 src/volcano_sdk/_generated/models/schedule_request_kind.py
create mode 100644 src/volcano_sdk/_generated/models/service_key.py
create mode 100644 src/volcano_sdk/_generated/models/set_project_git_production_branch_request.py
create mode 100644 src/volcano_sdk/_generated/models/start_git_connect_provider.py
create mode 100644 src/volcano_sdk/_generated/models/storage_bucket.py
create mode 100644 src/volcano_sdk/_generated/models/storage_copy_request.py
create mode 100644 src/volcano_sdk/_generated/models/storage_list_response.py
create mode 100644 src/volcano_sdk/_generated/models/storage_move_request.py
create mode 100644 src/volcano_sdk/_generated/models/storage_object.py
create mode 100644 src/volcano_sdk/_generated/models/storage_object_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/storage_object_with_bucket.py
create mode 100644 src/volcano_sdk/_generated/models/storage_object_with_bucket_metadata.py
create mode 100644 src/volcano_sdk/_generated/models/storage_policy.py
create mode 100644 src/volcano_sdk/_generated/models/storage_policy_operation.py
create mode 100644 src/volcano_sdk/_generated/models/storage_stats.py
create mode 100644 src/volcano_sdk/_generated/models/storage_visibility_request.py
create mode 100644 src/volcano_sdk/_generated/models/summarize_project_deployments_resource_type.py
create mode 100644 src/volcano_sdk/_generated/models/test_email_request.py
create mode 100644 src/volcano_sdk/_generated/models/test_email_response.py
create mode 100644 src/volcano_sdk/_generated/models/unban_user_response.py
create mode 100644 src/volcano_sdk/_generated/models/unban_user_response_status.py
create mode 100644 src/volcano_sdk/_generated/models/update_auth_config_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_auth_config_request_allowed_email_domains_mode.py
create mode 100644 src/volcano_sdk/_generated/models/update_auth_hosted_page_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_database_branch_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_database_type_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_database_type_request_database_type.py
create mode 100644 src/volcano_sdk/_generated/models/update_email_template_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_email_template_type.py
create mode 100644 src/volcano_sdk/_generated/models/update_function_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_function_scheduler_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_function_scheduler_request_payload.py
create mode 100644 src/volcano_sdk/_generated/models/update_o_auth_config_provider.py
create mode 100644 src/volcano_sdk/_generated/models/update_o_auth_config_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_project_git_deploy_settings_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_project_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_realtime_config_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_storage_bucket_request.py
create mode 100644 src/volcano_sdk/_generated/models/update_variable_request.py
create mode 100644 src/volcano_sdk/_generated/models/upload_project_logo_body.py
create mode 100644 src/volcano_sdk/_generated/models/upload_session_part.py
create mode 100644 src/volcano_sdk/_generated/models/upload_session_status_response.py
create mode 100644 src/volcano_sdk/_generated/models/upload_session_status_response_status.py
create mode 100644 src/volcano_sdk/_generated/models/upload_storage_object_files_body.py
create mode 100644 src/volcano_sdk/_generated/models/upload_storage_object_x_upload_complete.py
create mode 100644 src/volcano_sdk/_generated/models/usage_data_point.py
create mode 100644 src/volcano_sdk/_generated/models/variable.py
create mode 100644 src/volcano_sdk/_generated/models/variable_deploy_source.py
create mode 100644 src/volcano_sdk/_generated/models/variable_status.py
create mode 100644 src/volcano_sdk/_generated/types.py
create mode 100644 src/volcano_sdk/_transport.py
create mode 100644 src/volcano_sdk/auth.py
create mode 100644 src/volcano_sdk/database.py
create mode 100644 src/volcano_sdk/errors.py
create mode 100644 src/volcano_sdk/locks.py
create mode 100644 src/volcano_sdk/models.py
create mode 100644 src/volcano_sdk/realtime.py
create mode 100644 src/volcano_sdk/storage.py
create mode 100644 tests/fixtures/sdk-contract-dry-run.json
create mode 100644 tests/unit/test_contract_bindings.py
create mode 100644 tests/unit/test_errors.py
create mode 100644 tests/unit/test_facade.py
create mode 100644 tests/unit/test_generated_transport.py
create mode 100644 tests/unit/test_generation.py
create mode 100644 tests/unit/test_realtime.py
create mode 100644 tests/unit/test_state.py
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6afe61c7..34c823fc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -19,6 +19,13 @@ jobs:
python-version: ${{ matrix.python-version }}
- uses: astral-sh/setup-uv@v6
- run: uv sync --frozen
+ - run: uv run python scripts/check_openapi.py
- run: uv run ruff check .
- - run: uv run mypy .
- - run: uv run pytest
+ - run: uv run mypy
+ - run: uv run pytest tests/unit -q
+ - name: Check contract feature bindings
+ run: |
+ chmod 600 tests/fixtures/sdk-contract-dry-run.json
+ VOLCANO_SDK_CONTRACT_FIXTURE="$PWD/tests/fixtures/sdk-contract-dry-run.json" \
+ uv run behave features/contract --dry-run --no-snippets
+ - run: uv run python -m build
diff --git a/.gitignore b/.gitignore
index 4b868071..3874925c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ __pycache__/
build/
dist/
*.egg-info/
+reports/
diff --git a/README.md b/README.md
index 473b18a5..8fbe5187 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,83 @@
# Volcano Python SDK
-Official Python SDK for Volcano.
+This private proof of concept validates Volcano's Python SDK contract. It is not
+published to PyPI and is not ready for production use.
+
+## Try the contract facade
+
+The REST facade is synchronous. Create one client, sign in, and use the stored
+session for database and storage requests. Configure a service key for locks.
+
+```python
+from volcano_sdk import VolcanoClient
+
+client = VolcanoClient(
+ api_url="https://api.volcano.dev",
+ anon_key="your-anon-key",
+ service_key="your-service-key",
+)
+
+session = client.auth.sign_in(email="user@example.com", password="secret")
+
+rows = (
+ client.database("main")
+ .from_("items")
+ .select("*")
+ .eq("slug", "a")
+ .execute()
+)
+
+bucket = client.storage.from_("assets")
+bucket.upload("a.txt", b"hello")
+downloaded = bucket.download("a.txt")
+assert downloaded == b"hello"
+
+lease = client.locks.acquire("build", ttl=30)
+client.locks.release("build", lease)
+```
+
+Realtime is async. Channels wrap `centrifuge-python`; the underlying client and
+subscription objects are not part of the public API.
+
+```python
+channel = client.realtime.channel("updates")
+channel.on("message", print)
+
+await channel.subscribe()
+await channel.send({"event": "message", "value": "contract"})
+await channel.unsubscribe()
+await client.realtime.disconnect()
+```
+
+## Compatibility
+
+The POC supports Python 3.11 and 3.14. Its public facade is intentionally
+independent of generated httpx types. Compatibility is verified against the
+bundled Volcano API contract from hosting commit
+`a3f4a6e9d0fb48a16621383bd796d8b0d1378630`; `openapi/openapi.yaml` has SHA-256
+`c26ab2f32961699b19f710c1174906b7baae077eefcec299a6c19a36d2f559f6`.
+
+The realtime wrapper includes a narrow compatibility adapter for Volcano's
+project-prefixed publication channels. It still delegates connection,
+subscription, publish, and disconnect behavior to `centrifuge-python` 0.6.
+
+## Develop locally
+
+```shell
+uv sync --frozen
+uv run python scripts/check_openapi.py
+uv run ruff check .
+uv run mypy
+uv run pytest tests/unit -q
+uv run python -m build
+```
+
+Live contract scenarios require an isolated fixture produced by
+`volcano-hosting/tests/sdk-contract/support/fixture.mjs`:
+
+```shell
+VOLCANO_SDK_CONTRACT_FIXTURE=/absolute/path/to/fixture.json \
+ uv run behave features/contract --junit --junit-directory reports/behave
+```
+
+The fixture must be an absolute path to a mode-`0600` JSON file.
diff --git a/features/contract/auth.feature b/features/contract/auth.feature
new file mode 100644
index 00000000..6c5f17b8
--- /dev/null
+++ b/features/contract/auth.feature
@@ -0,0 +1,8 @@
+Feature: SDK authentication contract
+
+ @auth @SDK-AUTH-001
+ Scenario: Successful password sign-in creates a usable session
+ Given the confirmed contract user
+ When the client signs in with the contract user's credentials
+ Then the SDK operation succeeds
+ And the current session belongs to the contract user
diff --git a/features/contract/database.feature b/features/contract/database.feature
new file mode 100644
index 00000000..1accc448
--- /dev/null
+++ b/features/contract/database.feature
@@ -0,0 +1,8 @@
+Feature: SDK database contract
+
+ @database @SDK-DB-001
+ Scenario: Equality filters select the matching row
+ Given an authenticated client
+ When the client selects the contract table where "slug" equals the fixture slug
+ Then the SDK operation succeeds
+ And exactly the fixture row is returned
diff --git a/features/contract/locks.feature b/features/contract/locks.feature
new file mode 100644
index 00000000..dceff4a4
--- /dev/null
+++ b/features/contract/locks.feature
@@ -0,0 +1,8 @@
+Feature: SDK lock contract
+
+ @locks @SDK-LOCKS-001
+ Scenario: An acquired lock can be released
+ Given a service-role client
+ When the client acquires and releases the contract lock
+ Then the SDK operation succeeds
+ And the released lease is no longer held
diff --git a/features/contract/realtime.feature b/features/contract/realtime.feature
new file mode 100644
index 00000000..dac470bd
--- /dev/null
+++ b/features/contract/realtime.feature
@@ -0,0 +1,8 @@
+Feature: SDK realtime contract
+
+ @realtime @SDK-REALTIME-001
+ Scenario: Broadcast reaches another subscribed client
+ Given two authenticated realtime clients
+ When one client subscribes and the other publishes the contract message
+ Then the SDK operation succeeds
+ And the subscriber receives the contract message within 10 seconds
diff --git a/features/contract/storage.feature b/features/contract/storage.feature
new file mode 100644
index 00000000..80972145
--- /dev/null
+++ b/features/contract/storage.feature
@@ -0,0 +1,8 @@
+Feature: SDK storage contract
+
+ @storage @SDK-STORAGE-001
+ Scenario: Uploaded bytes can be downloaded unchanged
+ Given an authenticated client
+ When the client uploads and downloads the contract object
+ Then the SDK operation succeeds
+ And the downloaded bytes equal the uploaded bytes
diff --git a/features/contract_support.py b/features/contract_support.py
new file mode 100644
index 00000000..e77c1465
--- /dev/null
+++ b/features/contract_support.py
@@ -0,0 +1,146 @@
+from __future__ import annotations
+
+import asyncio
+import os
+import secrets
+from collections.abc import Awaitable, Callable
+from dataclasses import dataclass
+from typing import Any
+
+from centrifuge import CentrifugeError
+
+from volcano_sdk import (
+ AuthenticationError,
+ ConflictError,
+ NotFoundError,
+ RateLimitedError,
+ ServerError,
+ TransportError,
+ ValidationError,
+ VolcanoClient,
+ VolcanoError,
+)
+from volcano_sdk.models import LockLease
+from volcano_sdk.realtime import Channel
+
+CONTRACT_EXCEPTIONS = (
+ CentrifugeError,
+ KeyError,
+ OSError,
+ RuntimeError,
+ TypeError,
+ ValueError,
+ VolcanoError,
+)
+
+
+@dataclass(frozen=True, slots=True)
+class Outcome:
+ ok: bool
+ value: Any = None
+ category: str | None = None
+ error: Exception | None = None
+
+
+def classify_error(error: Exception) -> str:
+ categories = (
+ (AuthenticationError, "authentication error"),
+ (ValidationError, "validation error"),
+ (NotFoundError, "not found"),
+ (ConflictError, "conflict"),
+ (RateLimitedError, "rate limited"),
+ (ServerError, "server error"),
+ (TransportError, "transport error"),
+ )
+ for error_type, category in categories:
+ if isinstance(error, error_type):
+ return category
+ if isinstance(error, VolcanoError):
+ status = error.status
+ if status in (401, 403):
+ return "authentication error"
+ if status in (400, 422):
+ return "validation error"
+ if status == 404:
+ return "not found"
+ if status == 409:
+ return "conflict"
+ if status == 429:
+ return "rate limited"
+ if status is not None and 500 <= status <= 599:
+ return "server error"
+ return "transport error"
+
+
+class ContractWorld:
+ def __init__(self, fixture: dict[str, Any]) -> None:
+ self.fixture = fixture
+ self.client = VolcanoClient(
+ api_url=fixture["api_url"],
+ anon_key=fixture["anon_key"],
+ )
+ self.service_client = VolcanoClient(
+ api_url=fixture["api_url"],
+ anon_key=fixture["anon_key"],
+ service_key=fixture["service_key"],
+ )
+ suffix = f"py-{os.getpid()}-{secrets.token_hex(5)}"
+ self.storage_path = f"{fixture['storage_path']}.{suffix}"
+ self.realtime_channel = f"{fixture['realtime_channel']}-{suffix}"
+ self.lock_key = f"{fixture['lock_key']}-{suffix}"
+ self.storage_bytes = f"volcano-sdk-contract-{suffix}".encode()
+ self.realtime_message = {
+ "event": "message",
+ "value": f"volcano-sdk-contract-{suffix}",
+ }
+ self.last_outcome: Outcome | None = None
+ self.subscriber: Channel | None = None
+ self.publisher: Channel | None = None
+ self.realtime_clients: list[VolcanoClient] = []
+ self.cleanup_callbacks: list[Callable[[], None]] = []
+ self.loop = asyncio.new_event_loop()
+
+ def authenticate(self) -> None:
+ self.client.auth.sign_in(
+ email=self.fixture["user_email"],
+ password=self.fixture["user_password"],
+ )
+
+ def run(self, operation: Awaitable[Any]) -> Any:
+ return self.loop.run_until_complete(operation)
+
+ def record(self, operation: Callable[[], Any]) -> Outcome:
+ try:
+ self.last_outcome = Outcome(ok=True, value=operation())
+ except CONTRACT_EXCEPTIONS as error:
+ self.last_outcome = Outcome(
+ ok=False,
+ category=classify_error(error),
+ error=error,
+ )
+ return self.last_outcome
+
+ def register_lock_cleanup(self, key: str, lease: LockLease) -> Callable[[], None]:
+ def release() -> None:
+ self.service_client.locks.release(key, lease)
+
+ self.cleanup_callbacks.append(release)
+ return release
+
+ def cleanup(self) -> None:
+ failures: list[Exception] = []
+ for callback in reversed(self.cleanup_callbacks):
+ try:
+ callback()
+ except CONTRACT_EXCEPTIONS as error:
+ failures.append(error)
+ for client in self.realtime_clients:
+ try:
+ self.run(client.realtime.disconnect())
+ except CONTRACT_EXCEPTIONS as error:
+ failures.append(error)
+ self.cleanup_callbacks.clear()
+ self.realtime_clients.clear()
+ self.loop.close()
+ if failures:
+ raise ExceptionGroup("Python contract cleanup failed", failures)
diff --git a/features/environment.py b/features/environment.py
new file mode 100644
index 00000000..af22ef3c
--- /dev/null
+++ b/features/environment.py
@@ -0,0 +1,38 @@
+from __future__ import annotations
+
+import json
+import os
+import stat
+from pathlib import Path
+from typing import Any
+
+from contract_support import ContractWorld
+
+
+def load_fixture(path: Path) -> dict[str, Any]:
+ if not path.is_absolute():
+ raise ValueError("VOLCANO_SDK_CONTRACT_FIXTURE must be an absolute path")
+ mode = stat.S_IMODE(path.stat().st_mode)
+ if mode != 0o600:
+ raise PermissionError("VOLCANO_SDK_CONTRACT_FIXTURE must have mode 0600")
+ value = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(value, dict):
+ raise TypeError("VOLCANO_SDK_CONTRACT_FIXTURE must contain a JSON object")
+ return value
+
+
+def before_all(context: Any) -> None:
+ fixture_path = os.environ.get("VOLCANO_SDK_CONTRACT_FIXTURE")
+ if fixture_path is None:
+ raise RuntimeError("VOLCANO_SDK_CONTRACT_FIXTURE is required")
+ context.contract_fixture = load_fixture(Path(fixture_path))
+
+
+def before_scenario(context: Any, scenario: Any) -> None:
+ del scenario
+ context.contract = ContractWorld(context.contract_fixture)
+
+
+def after_scenario(context: Any, scenario: Any) -> None:
+ del scenario
+ context.contract.cleanup()
diff --git a/features/steps/sdk_contract_steps.py b/features/steps/sdk_contract_steps.py
new file mode 100644
index 00000000..82d3cab3
--- /dev/null
+++ b/features/steps/sdk_contract_steps.py
@@ -0,0 +1,192 @@
+from __future__ import annotations
+
+import asyncio
+from typing import Any
+
+from behave import given, then, when
+from contract_support import (
+ CONTRACT_EXCEPTIONS,
+ ContractWorld,
+ Outcome,
+ classify_error,
+)
+
+
+def _world(context: Any) -> ContractWorld:
+ return context.contract
+
+
+@given("the confirmed contract user")
+def confirmed_contract_user(context: Any) -> None:
+ assert _world(context).fixture["user_id"]
+
+
+@when("the client signs in with the contract user's credentials")
+def sign_in(context: Any) -> None:
+ world = _world(context)
+ world.record(
+ lambda: world.client.auth.sign_in(
+ email=world.fixture["user_email"],
+ password=world.fixture["user_password"],
+ )
+ )
+
+
+@then("the SDK operation succeeds")
+def operation_succeeds(context: Any) -> None:
+ outcome = _world(context).last_outcome
+ assert outcome is not None
+ assert outcome.ok, f"SDK operation failed ({outcome.category}): {outcome.error}"
+
+
+@then("the current session belongs to the contract user")
+def session_belongs_to_contract_user(context: Any) -> None:
+ world = _world(context)
+ assert world.last_outcome is not None
+ assert world.last_outcome.value.user_id == world.fixture["user_id"]
+ assert world.client.current_session is not None
+ assert world.client.current_session.user_id == world.fixture["user_id"]
+
+
+@given("an authenticated client")
+def authenticated_client(context: Any) -> None:
+ _world(context).authenticate()
+
+
+@when('the client selects the contract table where "slug" equals the fixture slug')
+def select_fixture_row(context: Any) -> None:
+ world = _world(context)
+ world.record(
+ lambda: world.client.database(world.fixture["database_name"])
+ .from_(world.fixture["table_name"])
+ .select("*")
+ .eq("slug", world.fixture["fixture_row"]["slug"])
+ .execute()
+ )
+
+
+@then("exactly the fixture row is returned")
+def fixture_row_returned(context: Any) -> None:
+ world = _world(context)
+ assert world.last_outcome is not None
+ assert world.last_outcome.value == [world.fixture["fixture_row"]]
+
+
+@when("the client uploads and downloads the contract object")
+def upload_and_download(context: Any) -> None:
+ world = _world(context)
+
+ def operation() -> bytes:
+ bucket = world.client.storage.from_(world.fixture["bucket_name"])
+ bucket.upload(world.storage_path, world.storage_bytes)
+ return bucket.download(world.storage_path)
+
+ world.record(operation)
+
+
+@then("the downloaded bytes equal the uploaded bytes")
+def downloaded_bytes_match(context: Any) -> None:
+ world = _world(context)
+ assert world.last_outcome is not None
+ assert world.last_outcome.value == world.storage_bytes
+
+
+@given("a service-role client")
+def service_role_client(context: Any) -> None:
+ assert _world(context).fixture["service_key"]
+
+
+@when("the client acquires and releases the contract lock")
+def acquire_and_release_lock(context: Any) -> None:
+ world = _world(context)
+
+ def operation() -> dict[str, Any]:
+ lease = world.service_client.locks.acquire(world.lock_key, ttl=10)
+ cleanup = world.register_lock_cleanup(world.lock_key, lease)
+ world.service_client.locks.release(world.lock_key, lease)
+ world.cleanup_callbacks.remove(cleanup)
+
+ replacement = world.service_client.locks.acquire(world.lock_key, ttl=10)
+ replacement_cleanup = world.register_lock_cleanup(world.lock_key, replacement)
+ world.service_client.locks.release(world.lock_key, replacement)
+ world.cleanup_callbacks.remove(replacement_cleanup)
+ return {"lease": lease, "released": replacement.token != lease.token}
+
+ world.record(operation)
+
+
+@then("the released lease is no longer held")
+def released_lease_not_held(context: Any) -> None:
+ world = _world(context)
+ assert world.last_outcome is not None
+ assert world.last_outcome.value["released"] is True
+
+
+@given("two authenticated realtime clients")
+def two_realtime_clients(context: Any) -> None:
+ world = _world(context)
+ try:
+ clients = [
+ world.client,
+ type(world.client)(
+ api_url=world.fixture["api_url"],
+ anon_key=world.fixture["anon_key"],
+ ),
+ ]
+ for client in clients:
+ client.auth.sign_in(
+ email=world.fixture["user_email"],
+ password=world.fixture["user_password"],
+ )
+ world.realtime_clients = clients
+ world.subscriber = clients[0].realtime.channel(world.realtime_channel)
+ world.publisher = clients[1].realtime.channel(world.realtime_channel)
+ async def subscribe() -> None:
+ await asyncio.gather(
+ world.subscriber.subscribe(),
+ world.publisher.subscribe(),
+ )
+
+ world.run(subscribe())
+ except CONTRACT_EXCEPTIONS as error:
+ world.last_outcome = Outcome(
+ ok=False,
+ category=classify_error(error),
+ error=error,
+ )
+
+
+@when("one client subscribes and the other publishes the contract message")
+def subscribe_and_publish(context: Any) -> None:
+ world = _world(context)
+ if world.last_outcome is not None and not world.last_outcome.ok:
+ return
+
+ async def operation() -> Any:
+ assert world.subscriber is not None
+ assert world.publisher is not None
+ received = world.loop.create_future()
+
+ def on_message(message: Any) -> None:
+ if not received.done():
+ received.set_result(message)
+
+ world.subscriber.on("message", on_message)
+ await world.publisher.send(world.realtime_message)
+ return await asyncio.wait_for(received, timeout=10)
+
+ try:
+ world.last_outcome = Outcome(ok=True, value=world.run(operation()))
+ except CONTRACT_EXCEPTIONS as error:
+ world.last_outcome = Outcome(
+ ok=False,
+ category=classify_error(error),
+ error=error,
+ )
+
+
+@then("the subscriber receives the contract message within 10 seconds")
+def subscriber_received_message(context: Any) -> None:
+ world = _world(context)
+ assert world.last_outcome is not None
+ assert world.last_outcome.value == world.realtime_message
diff --git a/openapi-python-client.yaml b/openapi-python-client.yaml
new file mode 100644
index 00000000..ec1897f8
--- /dev/null
+++ b/openapi-python-client.yaml
@@ -0,0 +1,5 @@
+package_name_override: _generated
+project_name_override: volcano-sdk-generated
+literal_enums: true
+use_path_prefixes_for_title_model_names: false
+post_hooks: []
diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml
new file mode 100644
index 00000000..fc21a13e
--- /dev/null
+++ b/openapi/openapi.yaml
@@ -0,0 +1,16286 @@
+openapi: 3.0.3
+info:
+ title: Volcano Hosting API
+ description: |-
+ Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000).
+
+ This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations.
+ version: 3.0.0
+ contact:
+ name: Volcano Hosting
+ email: support@volcano.dev
+servers:
+ - url: https://api.volcano.dev
+ description: Production API server
+ - url: http://localhost:8000
+ description: Development API server (use VOLCANO_API_URL env var)
+tags:
+ - name: Projects
+ description: Project management operations
+ - name: Logs
+ description: Project-scoped log search and activity APIs
+ - name: Functions
+ description: Function deployment and management
+ - name: Frontends
+ description: Frontend deployment and management. Supports Next.js 15.x and 16.x with Node.js 22.x or 24.x inferred from package.json engines.node when the selected Node.js family satisfies the installed Next.js package engines.node constraint.
+ - name: Tokens
+ description: Service keys for function invocation and database admin access
+ - name: Variables
+ description: Environment variable management
+ - name: Databases
+ description: Serverless PostgreSQL database provisioning and management
+ - name: Database Branches
+ description: Short-lived forks of a database for development and testing
+ - name: Database Queries
+ description: REST API for querying databases (SELECT, INSERT, UPDATE, DELETE)
+ - name: Authentication
+ description: End-user authentication (signup, signin, profile)
+ - name: Auth Admin
+ description: Auth user management (platform admin only)
+ - name: Auth Configuration
+ description: Authentication settings and anon keys
+ - name: Anon Keys
+ description: Project-specific public keys for frontend auth
+ - name: Service Keys
+ description: Project-specific secret keys for admin operations (bypass RLS - backend only!)
+ - name: OAuth Configuration
+ description: OAuth provider configuration (Google, GitHub, Microsoft, Apple)
+ - name: OAuth Authentication
+ description: OAuth login flows and provider management for end users
+ - name: Git Connections
+ description: Platform-user git provider connections for deployment source integrations
+ - name: Project Imports
+ description: Read-only project source discovery and import readiness checks
+ - name: Storage Buckets
+ description: Storage bucket management (platform admin)
+ - name: Storage Policies
+ description: Storage access policy management (platform admin)
+ - name: Storage Admin
+ description: Storage statistics and cross-bucket object listing (platform admin)
+ - name: Storage Objects
+ description: File upload, download, and management (SDK-facing)
+ - name: Locks
+ description: Project-scoped leases for backend coordination (service-role keys only)
+ - name: Realtime
+ description: WebSocket realtime configuration and monitoring
+ - name: System
+ description: System health and monitoring endpoints
+ - name: CLI Authentication
+ description: |
+ Browser-based CLI login flow for automatic token provisioning.
+ The CLI creates a session, opens a browser for user authentication,
+ and polls for completion. Session completion is handled by volcano.dev
+ via the Management API.
+paths:
+ /user/imports/connect:
+ post:
+ tags:
+ - Project Imports
+ summary: Start a project import provider connection
+ description: |
+ Starts a first-party dashboard user's provider connection flow. The
+ response sets a short-lived HttpOnly browser-binding cookie for the
+ public provider callback.
+ operationId: startImportConnect
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: query
+ required: false
+ description: Import provider to connect. Defaults to Vercel.
+ schema:
+ $ref: '#/components/schemas/ImportProvider'
+ - name: redirect
+ in: query
+ required: false
+ description: Validated application URL used after the provider callback.
+ schema:
+ type: string
+ format: uri
+ pattern: ^https://[^/?#]+(?:[/?][^#]*)?$|^http://(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?(?:[/?][^#]*)?$
+ responses:
+ '200':
+ description: Provider authorization URL
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ImportConnectStartResponse'
+ '400':
+ description: Unsupported provider or invalid redirect
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to start the connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Import provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /imports/{provider}/callback:
+ get:
+ tags:
+ - Project Imports
+ summary: Complete a project import provider connection
+ description: |
+ Public provider callback protected by signed state and the browser-binding
+ cookie created by startImportConnect.
+ operationId: completeImportConnect
+ security: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/ImportProvider'
+ - name: state
+ in: query
+ required: true
+ description: Signed connect state generated by startImportConnect.
+ schema:
+ type: string
+ - name: code
+ in: query
+ required: false
+ description: Provider authorization code.
+ schema:
+ type: string
+ - name: error
+ in: query
+ required: false
+ description: Provider error category.
+ schema:
+ type: string
+ - name: teamId
+ in: query
+ required: false
+ description: Vercel team selected during installation.
+ schema:
+ type: string
+ - name: configurationId
+ in: query
+ required: false
+ description: Vercel Integration configuration identifier.
+ schema:
+ type: string
+ - name: next
+ in: query
+ required: false
+ description: Provider completion URL validated by the provider adapter.
+ schema:
+ type: string
+ - name: source
+ in: query
+ required: false
+ description: Vercel installation source indicator.
+ schema:
+ type: string
+ responses:
+ '303':
+ description: Redirect to the provider completion URL, signed application redirect, or Volcano import page
+ headers:
+ Location:
+ description: Validated redirect target
+ schema:
+ type: string
+ '400':
+ description: Invalid callback request, state, or browser binding
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Too many callback attempts
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to complete the connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Import provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /user/imports/connections:
+ get:
+ tags:
+ - Project Imports
+ summary: List project import provider connections
+ operationId: listImportConnections
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ responses:
+ '200':
+ description: Stored import provider connections
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ImportConnectionsResponse'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to list connections
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /user/imports/connections/{connectionId}:
+ delete:
+ tags:
+ - Project Imports
+ summary: Delete a project import provider connection
+ operationId: deleteImportConnection
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: connectionId
+ in: path
+ required: true
+ description: Connection ID to delete.
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Connection deleted
+ '400':
+ description: Malformed connection ID
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Connection not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Connection changed while it was being deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to delete the connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Import provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /imports/{provider}/sources:
+ get:
+ tags:
+ - Project Imports
+ summary: List project sources available from a provider connection
+ description: Lists provider projects without changing provider or Volcano resources.
+ operationId: listImportSources
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/ImportProvider'
+ - name: connection_id
+ in: query
+ required: true
+ description: Owned provider connection used for discovery.
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Provider sources available to import
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ImportSourcesResponse'
+ '400':
+ description: Invalid provider or connection ID
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: The provider connection lacks a required Integration scope
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Connection or provider source not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: The provider connection must be reconnected
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Provider rate limit exceeded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to list provider sources
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Provider unavailable or integration not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /imports/{provider}/preflight:
+ post:
+ tags:
+ - Project Imports
+ summary: Check whether a provider project is ready to import
+ description: Produces a deterministic read-only readiness report for a proposed new Volcano project.
+ operationId: preflightProjectImport
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/ImportProvider'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectImportPreflightRequest'
+ responses:
+ '200':
+ description: Import readiness report
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectImportReport'
+ '400':
+ description: Invalid provider, source, project name, or target
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: The provider connection lacks a required Integration scope
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Connection or provider source not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: The provider connection must be reconnected
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Provider rate limit exceeded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to produce an import readiness report
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Provider unavailable or integration not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /imports/{provider}/runs:
+ post:
+ tags:
+ - Project Imports
+ summary: Start a Vercel project import
+ description: Creates a Volcano project from an importable production preflight report. Retrying the same request with the same Idempotency-Key returns the existing run.
+ operationId: startProjectImport
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/ImportProvider'
+ - name: Idempotency-Key
+ in: header
+ required: true
+ schema:
+ type: string
+ minLength: 1
+ maxLength: 255
+ pattern: ^[!-~]+$
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectImportStartRequest'
+ responses:
+ '202':
+ description: Import run accepted
+ headers:
+ Location:
+ required: true
+ schema:
+ type: string
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectImportRun'
+ '400':
+ description: Invalid request or idempotency key
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Provider permission or project admission denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Connection or provider source not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Preflight is stale, idempotency key was reused, or destination conflicts
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '422':
+ description: Source is not importable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Provider rate limit exceeded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to start the import
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Provider unavailable or integration not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /imports/{provider}/runs/{runId}:
+ get:
+ tags:
+ - Project Imports
+ summary: Get a project import run
+ operationId: getProjectImportRun
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/ImportProvider'
+ - name: runId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Import run status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectImportRun'
+ '400':
+ description: Invalid import run ID
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Import run not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to get the import run
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /user/git/connect:
+ post:
+ tags:
+ - Git Connections
+ summary: Start a git provider connection
+ description: |
+ Starts a first-party dashboard user's git provider connection flow and
+ returns the provider authorization URL. The response also sets a
+ short-lived HttpOnly callback binding cookie tied to the authenticated
+ user through the signed provider state.
+ operationId: startGitConnect
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: query
+ required: false
+ description: Git provider to connect. Defaults to github.
+ schema:
+ type: string
+ enum:
+ - github
+ default: github
+ - name: redirect
+ in: query
+ required: false
+ description: URL to redirect the browser to after the provider callback completes.
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Provider authorization URL
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GitConnectStartResponse'
+ '400':
+ description: Unsupported provider or invalid redirect
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to start the connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Git provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /user/git/connections:
+ get:
+ tags:
+ - Git Connections
+ summary: List git provider connections
+ operationId: listGitConnections
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ responses:
+ '200':
+ description: Stored git provider connections
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GitConnectionsResponse'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to list connections
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Git provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /user/git/connections/{connectionId}:
+ delete:
+ tags:
+ - Git Connections
+ summary: Delete a git provider connection
+ operationId: deleteGitConnection
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: connectionId
+ in: path
+ required: true
+ description: Connection ID to delete
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Connection deleted
+ '400':
+ description: Malformed connection ID
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Connection not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to delete connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Git provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /user/git/connections/{connectionId}/installations:
+ get:
+ tags:
+ - Git Connections
+ summary: List GitHub App installations accessible to a connection
+ description: |
+ Live proxy to GitHub: lists the platform GitHub App installations the
+ connection's stored user token can access. Nothing is persisted by
+ this call.
+ operationId: listGitInstallations
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: connectionId
+ in: path
+ required: true
+ description: Connection ID to browse installations for.
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Installations accessible to the connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GitInstallationsResponse'
+ '400':
+ description: Malformed connection ID
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Connection not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to list installations
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Git provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /user/git/connections/{connectionId}/installations/{installationId}/repositories:
+ get:
+ tags:
+ - Git Connections
+ summary: List repos accessible to a connection through an installation
+ description: |
+ Live proxy to GitHub: lists the repos the connection's stored user
+ token can access through installationId. Nothing is persisted by this
+ call.
+ operationId: listGitInstallationRepositories
+ security:
+ - UserToken: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: connectionId
+ in: path
+ required: true
+ description: Connection ID to browse repositories for.
+ schema:
+ type: string
+ format: uuid
+ - name: installationId
+ in: path
+ required: true
+ description: GitHub App installation ID.
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Repositories accessible through the installation
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GitRepositoriesResponse'
+ '400':
+ description: Malformed connection or installation ID
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Connection not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to list repositories
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Git provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /github/callback:
+ get:
+ tags:
+ - Git Connections
+ summary: Complete a GitHub App connection callback
+ description: |
+ Public GitHub App callback. The signed state and callback binding cookie
+ bind the provider authorization to the browser that started the flow.
+ operationId: gitConnectCallback
+ security: []
+ parameters:
+ - name: code
+ in: query
+ required: false
+ description: GitHub user authorization code.
+ schema:
+ type: string
+ - name: state
+ in: query
+ required: true
+ description: Signed connect state generated by startGitConnect.
+ schema:
+ type: string
+ - name: error
+ in: query
+ required: false
+ description: Provider error returned by GitHub.
+ schema:
+ type: string
+ responses:
+ '303':
+ description: Redirect back to the app after a successful or failed connect attempt
+ headers:
+ Location:
+ description: Redirect target
+ schema:
+ type: string
+ '400':
+ description: Invalid callback request or state
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Too many callback attempts from this client
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to complete the connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Git provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects:
+ get:
+ tags:
+ - Projects
+ summary: List all projects for authenticated user
+ description: |
+ Returns projects that are not deleting or deleted, newest first.
+ Supports two mutually exclusive pagination modes. Offset mode uses
+ `page` and `limit`. Cursor mode uses `cursor` or `ending_before` with
+ `limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded
+ `offset` past the cursor anchor. Supplying `limit` without `page`
+ selects cursor mode. `search` applies a case-insensitive project-name
+ filter in either mode. Sending `page` with `cursor` or `ending_before`,
+ or sending both cursor directions, returns 400.
+ operationId: listProjects
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedProjects'
+ '400':
+ description: Invalid or conflicting pagination parameters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ post:
+ tags:
+ - Projects
+ summary: Create a new project
+ description: |
+ Creates a project for the authenticated user.
+ Each user can create up to 1,000 projects. Requests over this cap return 403.
+ operationId: createProject
+ security:
+ - UserToken: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateProjectRequest'
+ responses:
+ '201':
+ description: Project created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ '400':
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Project limit exceeded for the user
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}:
+ get:
+ tags:
+ - Projects
+ summary: Get project by ID
+ operationId: getProject
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ patch:
+ tags:
+ - Projects
+ summary: Update project metadata and region policy
+ operationId: updateProject
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateProjectRequest'
+ responses:
+ '200':
+ description: Project updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ '400':
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden (for example, selecting subset regions on non-PRO plan)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Conflict (project name already exists or a resource deployment blocks a region change)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Projects
+ summary: Delete a project
+ description: |
+ Starts asynchronous project deletion. The project remains available from
+ `GET /projects/{id}` with `status: deleting` until cleanup finishes, but is
+ removed from project lists as soon as deletion starts. After cleanup it
+ returns 404.
+ operationId: deleteProject
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '202':
+ description: Project deletion started
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/health:
+ get:
+ tags:
+ - Projects
+ summary: Get project health
+ description: |
+ Returns a fast control-plane health snapshot for the project and its
+ deployed resources. The endpoint does not run live provider probes.
+ A successful request returns 200 even when the project status is
+ `unhealthy`; transport and authorization failures use HTTP errors.
+ operationId: getProjectHealth
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Project health snapshot retrieved
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectHealthResponse'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/metrics/query:
+ post:
+ tags:
+ - Projects
+ summary: Query project runtime metrics
+ description: |
+ Evaluates a batch of named, curated runtime metric queries over one
+ trailing time range. Query IDs correlate each request with its result;
+ raw backend query languages are intentionally not exposed.
+ operationId: queryProjectMetrics
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectMetricsQueryRequest'
+ responses:
+ '200':
+ description: Project runtime metric queries evaluated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectMetricsQueryResponse'
+ '400':
+ description: Invalid metric query
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Runtime metrics backend unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/logo:
+ get:
+ tags:
+ - Projects
+ summary: Get the project logo image
+ description: |
+ Returns the raw logo image stored in the project's storage folder. This
+ endpoint is unauthenticated so the asset can be rendered directly in an
+ `
` tag; project IDs are unguessable UUIDs and logos are
+ non-sensitive branding. The `Project.logo_url` field exposes a versioned
+ path to this endpoint.
+ operationId: getProjectLogo
+ security: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Logo image
+ content:
+ image/png:
+ schema:
+ type: string
+ format: binary
+ image/jpeg:
+ schema:
+ type: string
+ format: binary
+ image/gif:
+ schema:
+ type: string
+ format: binary
+ image/webp:
+ schema:
+ type: string
+ format: binary
+ image/svg+xml:
+ schema:
+ type: string
+ format: binary
+ '404':
+ description: Project or logo not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ post:
+ tags:
+ - Projects
+ summary: Upload or replace the project logo
+ description: |
+ Uploads an image as the project's logo, storing it in the project's
+ storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any
+ existing logo. Returns the updated project, whose `logo_url` reflects
+ the new logo.
+ operationId: uploadProjectLogo
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ required:
+ - logo
+ properties:
+ logo:
+ type: string
+ format: binary
+ description: Logo image (PNG, JPEG, GIF, WebP, or SVG; max 2 MB)
+ responses:
+ '200':
+ description: Logo uploaded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ '400':
+ description: Bad request (missing file, unsupported type, or too large)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Project is being deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Logo storage is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Projects
+ summary: Remove the project logo
+ description: |
+ Deletes the project logo from the project's storage folder and clears its
+ record. Returns the updated project with no `logo_url`.
+ operationId: deleteProjectLogo
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Logo removed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Project is being deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Logo storage is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/usage:
+ get:
+ tags:
+ - Projects
+ summary: Get usage metrics for a project
+ description: |
+ Returns project usage totals for the current usage month plus
+ recent hourly and daily time series for each tracked metric.
+ operationId: getProjectUsage
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Usage metrics retrieved
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectUsageResponse'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/config:
+ get:
+ tags:
+ - Projects
+ summary: Export project configuration
+ description: |
+ Exports the project's current user-facing configuration as a
+ declarative manifest. Returns JSON by default. Request the canonical
+ volcano-config.yaml rendering with `Accept: application/yaml` or
+ `?format=yaml`; the YAML is returned verbatim as the raw response body
+ (`Content-Type: application/yaml`) and is meant to be saved as-is.
+ Write-only secrets (SMTP password, OAuth client secrets, TLS material)
+ are omitted from the export; the YAML rendering adds a header comment
+ describing how to set them via CLI environment interpolation.
+ operationId: getProjectConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: format
+ in: query
+ required: false
+ description: Response format override. Takes precedence over the Accept header.
+ schema:
+ type: string
+ enum:
+ - json
+ - yaml
+ responses:
+ '200':
+ description: |
+ Current project configuration. JSON by default; when YAML is
+ requested the body is the canonical volcano-config.yaml document
+ served verbatim with `Content-Type: application/yaml`.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectConfig'
+ application/yaml:
+ schema:
+ type: string
+ format: binary
+ description: |
+ Canonical volcano-config.yaml document returned verbatim,
+ ready to be saved as-is.
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ put:
+ tags:
+ - Projects
+ summary: Apply project configuration
+ description: |
+ Validates and applies a declarative configuration manifest to the
+ project, reconciling each declared section and returning a per-resource
+ report. Omitted sections are untouched. Declared collection keys
+ (`variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, `functions[].schedulers`) are fully synced:
+ resources absent from the manifest are deleted. Functions, frontends,
+ databases, and buckets are never created or deleted; manifest entries
+ for resources that do not exist are skipped and reported in `skipped`,
+ and existing resources missing from a declared section are reported in
+ `missing`. Validation failures (including plan-gate violations) return
+ 422 and nothing is applied. Set `dry_run=true` to get the projected
+ report without applying changes. Applies are serialized per project;
+ a concurrent apply returns 409.
+ operationId: applyProjectConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: dry_run
+ in: query
+ required: false
+ description: Validate and report projected actions without applying changes.
+ schema:
+ type: boolean
+ default: false
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectConfig'
+ responses:
+ '200':
+ description: |
+ Apply report. Individual entries may still carry `action: error`
+ for apply-phase failures (summary.errors > 0); already-applied
+ changes are not rolled back.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectConfigApplyResult'
+ '400':
+ description: Malformed request body
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Another apply is in progress for this project
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '422':
+ description: Manifest validation failed; nothing was applied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectConfigValidationErrorResponse'
+ /projects/{id}/git-connection/production-branch:
+ put:
+ tags:
+ - Projects
+ - Git Connections
+ summary: Set the branch a project deploys from
+ description: |
+ Changes only the production branch, leaving the repository binding
+ alone. PUT /projects/{id}/git-connection can also set it, but that is a
+ full rebind: it needs connection_id, installation_id and a repository
+ selector resent, and re-resolves the repository against GitHub for a
+ field that does not depend on it.
+
+ The branch does not have to exist. It is validated as a Git branch name
+ and nothing more, so a project can be pointed at a branch that is about
+ to be pushed — the case a repository created empty depends on.
+
+ Setting the branch here marks it as the project's own choice, so a later
+ default-branch rename on GitHub no longer moves it. Projects that never
+ set one keep following the repository's default branch.
+ operationId: setProjectGitProductionBranch
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetProjectGitProductionBranchRequest'
+ responses:
+ '200':
+ description: The project's repo connection, with the new branch
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectGitConnection'
+ '400':
+ description: |
+ Malformed request body, or a production_branch that is not a valid
+ Git branch name
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Project not owned by the caller
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: |
+ Project not found, or it has no repository connected. The branch is
+ part of the connection, so there is nothing to set it on until one
+ exists.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to set the production branch
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/git-connection:
+ get:
+ tags:
+ - Projects
+ - Git Connections
+ summary: Get a project's repo connection
+ operationId: getProjectGitConnection
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: The project's current repo connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectGitConnection'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Project not owned by the caller
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found, or has no repo connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to get project git connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ put:
+ tags:
+ - Projects
+ - Git Connections
+ summary: Connect or update a project's repo connection
+ description: |
+ Full replace, following Vercel's model: many projects may point at the
+ same repo, so this only binds the project — it never creates or
+ deletes git-provider state. Used for both the initial connect and
+ later edits (repo change, root directory, production branch).
+ Resolves the repository_id or repo_full_name selector against the repos
+ accessible through installation_id via connection_id's stored GitHub
+ user token, then persists repository metadata only from that validated
+ GitHub response.
+ operationId: connectProjectGit
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ConnectProjectGitRequest'
+ responses:
+ '200':
+ description: The project's repo connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectGitConnection'
+ '400':
+ description: |
+ Malformed request body, no repository selector, selectors that
+ identify different repositories, a production_branch that is not a
+ valid Git branch name, no production_branch on a repository with no
+ default branch to follow (name one to connect a repository that has
+ no commits yet), or a production_branch other than the new
+ repository's default in a request that also changes repository.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: |
+ Project not owned by the caller, or the selected repository is not
+ accessible through installation_id
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project or connection not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to connect project git
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Git provider integration is not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Projects
+ - Git Connections
+ summary: Disconnect a project's repo connection
+ operationId: disconnectProjectGit
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '204':
+ description: Connection removed
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Project not owned by the caller
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found, or has no repo connection
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to disconnect project git
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/git-deploy-settings:
+ get:
+ tags:
+ - Projects
+ - Git Connections
+ summary: Get a project's Git auto-deploy settings
+ operationId: getProjectGitDeploySettings
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: The project's current Git auto-deploy settings
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectGitDeploySettings'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Project not owned by the caller
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to get project git deploy settings
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ put:
+ tags:
+ - Projects
+ - Git Connections
+ summary: Update a project's Git auto-deploy settings
+ description: |
+ Full replace of the project's Git auto-deploy settings: what a push to
+ the connected repo's production branch deploys.
+
+ Connecting a repository sets auto_deploy_enabled and deploy_functions
+ to true for a project that has never called this endpoint, so a push
+ deploys without any further setup. Once these settings have been saved
+ here they are the project's own: connecting, rebinding, disconnecting
+ and reconnecting all leave them untouched, including when they were
+ saved before any repository was connected. Frontend settings are off
+ until set here; the frontend need not exist when they are saved, since
+ frontend_name is resolved at deploy time.
+ operationId: updateProjectGitDeploySettings
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateProjectGitDeploySettingsRequest'
+ responses:
+ '200':
+ description: The project's updated Git auto-deploy settings
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectGitDeploySettings'
+ '400':
+ description: Malformed request body, or frontend_app_root without frontend_name
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Project not owned by the caller
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Failed to update project git deploy settings
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/databases/{databaseName}/queries:
+ get:
+ tags:
+ - Databases
+ summary: Get database queries
+ description: |
+ Returns the database's current top queries from pg_stat_statements
+ ranked by total execution time.
+
+ **PRO plan required.** This endpoint is only available to projects owned
+ by users on the PRO billing plan.
+ operationId: getProjectDatabaseQueries
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ - name: limit
+ in: query
+ description: Maximum number of queries to return.
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 10
+ responses:
+ '200':
+ description: Database query performance retrieved
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryPerformanceResponse'
+ '400':
+ description: Bad request - invalid query parameters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project or database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /deployments:
+ get:
+ tags:
+ - Projects
+ summary: List deployments across a user's projects
+ description: |
+ Lists Function and Frontend deployment attempts across every project the
+ user owns, newest first. Pass `project_id` to narrow the feed to a single
+ project.
+
+ Scope is project **ownership** (`projects.user_id`). `owner_id` names
+ whose deployments to return, not who started them — the actor is
+ `initiated_by_user_id`, which this endpoint does not filter on.
+
+ With a user token the scope is always the authenticated user: `owner_id`
+ may be omitted, or set to that same user, but naming anyone else is
+ refused with 403. Service callers on the management API must pass it,
+ since they have no authenticated user.
+
+ The owner is not checked for existence: an id with no projects returns an
+ empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is
+ polled to detect an event, so a caller needs `404` to keep meaning "this
+ route is not served here" — which is how a consumer notices it is running
+ against an older release. A mistyped owner therefore reads as "nothing
+ deployed"; callers that need to tell those apart should verify the user
+ through `GET /users/{id}` first.
+
+ Ordering is selectable. The default is the feed order — most recent
+ attempt first. `completed_at.asc` orders by completion, oldest first, and
+ considers only attempts that finished; combined with `limit=1` and a
+ `status` filter it answers "when did this user first succeed" in one
+ bounded query.
+
+ Both pagination modes are supported, selected exactly as
+ `/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a
+ `limit` with no `page`) uses keyset pagination; otherwise `page`/`limit`
+ offset pagination. `page` with a cursor, and `cursor` with
+ `ending_before`, are rejected.
+
+ A cursor is bound to every filter *and* to `order`, so changing any of
+ them mid-pagination rejects the cursor rather than silently skipping or
+ repeating rows. The keyset position is `(created_at, id)` for
+ `created_at.desc` and `(completed_at, id)` for `completed_at.asc`.
+ operationId: listDeployments
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/DeploymentOwnerId'
+ - name: project_id
+ in: query
+ required: false
+ description: Restrict the feed to a single project owned by the user.
+ schema:
+ type: string
+ format: uuid
+ - name: created_after
+ in: query
+ required: false
+ description: Restrict results to attempts created at or after this timestamp.
+ schema:
+ type: string
+ format: date-time
+ - $ref: '#/components/parameters/DeploymentResourceType'
+ - $ref: '#/components/parameters/DeploymentStatus'
+ - $ref: '#/components/parameters/DeploymentOperation'
+ - $ref: '#/components/parameters/DeploymentOrder'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedProjectDeployments'
+ '400':
+ description: Bad request - invalid filter or pagination
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - owner_id names a different user
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/deployments:
+ get:
+ tags:
+ - Projects
+ summary: List deployments in a project
+ description: |
+ Lists Function and Frontend deployment attempts across the project,
+ ordered most-recent first. Each item includes a normalized resource
+ reference so clients can render both resource types without extra
+ fetches.
+ operationId: listProjectDeployments
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ - name: created_after
+ in: query
+ required: false
+ description: Restrict results to attempts created at or after this timestamp.
+ schema:
+ type: string
+ format: date-time
+ - name: resource_type
+ in: query
+ required: false
+ description: |
+ Restrict the feed to a single resource type. Omit to return both
+ Function and Frontend deployments.
+ schema:
+ type: string
+ enum:
+ - function
+ - frontend
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedProjectDeployments'
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/deployments/summary:
+ get:
+ tags:
+ - Projects
+ summary: Summarize deployments in a project
+ description: |
+ Summarizes deployment attempts for one comparable resource pipeline.
+ Success rate uses conclusive outcomes only: active and deleted attempts
+ are successful; failed and degraded attempts are failures; in-progress
+ and superseded attempts are excluded. Median build duration includes
+ completed, non-superseded attempts with recorded build work,
+ including failed builds.
+ operationId: summarizeProjectDeployments
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: search
+ in: query
+ required: false
+ description: Restrict the summary to resource names containing this value.
+ schema:
+ type: string
+ - name: resource_type
+ in: query
+ required: true
+ description: Restrict the summary to one comparable deployment pipeline.
+ schema:
+ type: string
+ enum:
+ - function
+ - frontend
+ - name: created_after
+ in: query
+ required: false
+ description: Restrict results to attempts created at or after this timestamp.
+ schema:
+ type: string
+ format: date-time
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectDeploymentSummary'
+ '400':
+ description: Bad request - invalid identifier or filter
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/domains:
+ get:
+ tags:
+ - Frontends
+ summary: List all custom domains in a project
+ description: |
+ Project-scoped custom-domain list. Returns every active custom
+ domain across every frontend in the project (excludes soft-deleted
+ rows). Each item inlines the linked frontend's id and name so the
+ UI does not need a second fetch to render the "Linked to" column.
+ operationId: listProjectCustomDomains
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedProjectCustomDomains'
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/functions:
+ get:
+ tags:
+ - Functions
+ summary: List all functions in a project
+ description: |
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page`
+ and `search`) returns 400.
+ operationId: listFunctions
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedFunctions'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ post:
+ tags:
+ - Functions
+ summary: Create or update function code
+ description: |
+ Upload a serverless function source bundle. Direct API clients may send the function code
+ as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz
+ source archive.
+ Cloud deploys should include source files and dependency manifests/lockfiles, not installed
+ dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the
+ function compile build.
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container image is
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ Uploaded source archives cannot contain symlink entries. Safe symlinks created during
+ the cloud build are materialized before publish.
+ Volcano builds and deploys the function asynchronously after upload. A deployment that starts
+ immediately returns a Function resource with `status: provisioning`, then transitions to
+ `active` or `failed`. If another deployment is running, the response preserves the resource's
+ current status and exposes the queued deployment through `pending_deployment_id`.
+ Existing function traffic continues to use the last known-good runtime during an update. A failed
+ update keeps that runtime available and records the attempted deployment as failed.
+ Only one deployment runs for a given function. A newer request supersedes any queued request
+ and starts after the running deployment. Different functions and projects deploy concurrently.
+ If a function with the same name already exists in the project, this operation updates that
+ function's runtime, handler, and source bundle and returns `200 OK`.
+ Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403.
+ operationId: createFunction
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ required:
+ - name
+ - code
+ - runtime
+ properties:
+ name:
+ type: string
+ description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen)
+ maxLength: 63
+ pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
+ example: my-api-function
+ code:
+ type: string
+ format: binary
+ description: ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz source archive.
+ runtime:
+ type: string
+ enum:
+ - nodejs22.x
+ - nodejs24.x
+ - python3.10
+ - python3.11
+ - python3.12
+ - python3.13
+ - python3.14
+ - ruby3.3
+ - ruby3.4
+ - ruby4.0
+ description: |
+ Runtime environment. Required.
+ - Node.js: nodejs22.x, nodejs24.x
+ - Python: python3.10, python3.11, python3.12, python3.13, python3.14
+ - Ruby: ruby3.3, ruby3.4, ruby4.0
+ example: nodejs24.x
+ handler:
+ type: string
+ description: |
+ The name of the function to invoke. Defaults to "handler" if not specified.
+ Your code must export/define a function with this name:
+ - Node.js: exports.handler (in index.js)
+ - Python: def handler() (in main.py)
+ - Ruby: def handler() (in main.rb)
+ default: handler
+ example: handler
+ responses:
+ '200':
+ description: Existing function updated; its deployment was started or queued
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Function'
+ '201':
+ description: Function created and deployment workflow started
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Function'
+ '400':
+ description: Bad request (invalid file, too large, etc.)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Function limit exceeded for the project
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Function deletion is queued or running
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error (function deployment failed)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/functions/{functionId}:
+ get:
+ tags:
+ - Functions
+ summary: Get function by ID
+ operationId: getFunction
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Function'
+ '404':
+ description: Function not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ patch:
+ tags:
+ - Functions
+ summary: Update function settings
+ operationId: updateFunction
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateFunctionRequest'
+ examples:
+ makePublic:
+ summary: Make function public (anon keys can invoke)
+ value:
+ is_public: true
+ makePrivate:
+ summary: Make function private (default behavior)
+ value:
+ is_public: false
+ responses:
+ '200':
+ description: Function updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Function'
+ '400':
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Function not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Functions
+ summary: Delete a function
+ description: |
+ Schedules asynchronous function deletion. If another deployment is running, the function
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in function lists.
+ operationId: deleteFunction
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ responses:
+ '202':
+ description: Function deletion started or queued
+ '404':
+ description: Function not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /functions/{functionId}/invoke:
+ post:
+ tags:
+ - Functions
+ summary: Invoke a function
+ description: |
+ Invoke a serverless function.
+
+ **With Service Key** (admin/background operations):
+ - Use for background jobs, webhooks, cron, admin operations
+ - Function receives payload only (no user context)
+ - Database queries bypass RLS (admin access)
+
+ **With Auth User Token** (user-facing):
+ - Use for user-initiated actions
+ - Function receives payload + `__volcano_auth` context:
+ ```javascript
+ {
+ user_id: "uuid",
+ email: "user@example.com",
+ project_id: "uuid",
+ role: "authenticated" or "anonymous"
+ }
+ ```
+ - Database queries enforce RLS (user-scoped data)
+
+ **With Anon Key** (public function only):
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+ - Function receives payload only (no `__volcano_auth`)
+
+ **Transport and CORS:**
+ - Direct invocation endpoint is intended for `http://api./functions/{functionId}/invoke`
+ - DNS invocation endpoint is `https://{functionId}.functions./`
+ - CORS preflight for invocation allows only `POST, OPTIONS`
+ operationId: invokeFunction
+ security:
+ - AnonKey: []
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/FunctionId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionInvocationRequest'
+ examples:
+ serviceCall:
+ summary: Admin/background operation (service key)
+ value:
+ payload:
+ action: process_batch
+ items:
+ - 1
+ - 2
+ - 3
+ userCall:
+ summary: User-initiated call (auth token)
+ value:
+ payload:
+ action: get_profile
+ anonCall:
+ summary: Public function call (anon key)
+ value:
+ payload:
+ action: ping_public_endpoint
+ responses:
+ '200':
+ description: Function response (passthrough from function runtime)
+ headers:
+ X-Volcano-Version:
+ description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production)
+ schema:
+ type: string
+ X-Volcano-Region:
+ description: Region the function ran in (for example `us-east-1`)
+ schema:
+ type: string
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionInvocationResponse'
+ '400':
+ description: Bad request - invalid payload or function in failed state
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - CORS blocked, missing `functions.invoke`, or private function with anon key
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Function not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: |
+ Rate limit exceeded (per-function or project-wide limit), or the
+ owning platform user's billing-cycle bandwidth allowance (aggregate ingress +
+ egress) was exceeded.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: |
+ Function still provisioning or rate limiting service unavailable.
+ A freshly deployed (or updated) function may briefly report
+ `provisioning` and reject invocations until the background status
+ reconciler observes its deployment workflow completing and transitions
+ it to `active`. This is expected for a few seconds after deploy; clients
+ should retry.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ default:
+ description: Function response (passthrough; status code/body/headers come from the function)
+ headers:
+ X-Volcano-Version:
+ description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production)
+ schema:
+ type: string
+ X-Volcano-Region:
+ description: Region the function ran in (for example `us-east-1`)
+ schema:
+ type: string
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionInvocationResponse'
+ /functions/resolve:
+ get:
+ tags:
+ - Functions
+ summary: Resolve function name for invocation
+ description: |
+ Resolves a DNS-safe function name to its function ID within the caller's project.
+
+ SDKs use this endpoint internally to invoke by function name while routing by function ID.
+
+ **With Service Key**:
+ - Allowed
+
+ **With Auth User Token**:
+ - Allowed
+
+ **With Anon Key**:
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+ operationId: resolveFunctionForInvocation
+ security:
+ - AnonKey: []
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - name: name
+ in: query
+ required: true
+ schema:
+ type: string
+ maxLength: 63
+ pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
+ description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen)
+ example: my-function
+ responses:
+ '200':
+ description: Function resolved successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ResolveFunctionResponse'
+ '400':
+ description: Bad request - missing or invalid function name
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - CORS blocked or missing `functions.invoke` permission for anon key
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Function not found (or private function with anon key)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/logs/activity:
+ post:
+ tags:
+ - Logs
+ summary: Get project log activity
+ description: |
+ Retrieve bucketed log counts for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to count deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The activity window is limited
+ to the plan's retention window (FREE: 1 day, PRO: 30 days); older start
+ times are clamped to that window.
+ operationId: getProjectLogActivity
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LogActivityRequest'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LogActivityResponse'
+ '400':
+ description: Bad request - invalid query parameter
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project or resource not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/logs/search:
+ post:
+ tags:
+ - Logs
+ summary: Search project logs
+ description: |
+ Search or filter logs for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to read deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; requests for
+ `resource.type=database` from a FREE-plan project owner return 403.
+ Log history (runtime and deployment) is limited to the plan's retention
+ window (FREE: 1 day, PRO: 30 days); older time ranges are clamped to that
+ window.
+ operationId: searchProjectLogs
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LogSearchRequest'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LogSearchResponse'
+ '400':
+ description: Bad request - invalid query parameter
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project or resource not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/logs/stream:
+ post:
+ tags:
+ - Logs
+ summary: Stream project logs
+ description: |
+ Live-tail project logs as Server-Sent Events. The request body uses the
+ resource selector plus `q`, `start_time`, and `limit`,
+ including runtime logs and function/frontend deployment logs selected
+ with `resource.deployments`. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The `q` field uses the same
+ syntax as search and activity requests. Do not send `cursor` or
+ `end_time`; use `/logs/search` for range backfills.
+ Explicit historical `start_time` values are limited to the plan's
+ retention window (FREE: 1 day, PRO: 30 days). Resume with
+ `Last-Event-ID` or the `last_event_id` query parameter. The cursor is
+ bound to the request body: the resource selector and every filter must
+ match the original request when reconnecting, otherwise the request is
+ rejected with `400`.
+
+ This is a live tail, not a gap-free backfill. On connect or reconnect the
+ server delivers at most `limit` of the most recent matching events from
+ the cursor position and then follows new events; events older than that
+ window are not replayed. Use `/logs/search` to backfill a time range.
+ operationId: streamProjectLogs
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: Last-Event-ID
+ in: header
+ required: false
+ schema:
+ type: string
+ description: Opaque stream cursor from the most recent SSE `id` field.
+ - name: last_event_id
+ in: query
+ required: false
+ schema:
+ type: string
+ description: Opaque stream cursor fallback when setting `Last-Event-ID` is not practical.
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LogStreamRequest'
+ responses:
+ '200':
+ description: Server-Sent Events stream. `log` events contain a JSON `LogSearchEvent`; `warning` events contain a JSON object with an `error` field.
+ content:
+ text/event-stream:
+ schema:
+ type: string
+ examples:
+ log:
+ summary: Log event
+ value: |
+ : connected
+
+ id: STREAM_CURSOR
+ event: log
+ data: {"id":"LOG_EVENT_ID","timestamp":"2024-01-01T12:00:00Z","level":"info","message":"User logged in","resource":{"type":"function","id":"550e8400-e29b-41d4-a716-446655440000","name":"login"},"region":"us-east-1"}
+ '400':
+ description: Bad request - invalid selector, stream cursor, or unsupported stream field
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project or resource not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error - log streaming setup failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/functions/batch:
+ post:
+ tags:
+ - Functions
+ summary: Deploy multiple functions in one request
+ description: |
+ Upload multiple function source archives in one multipart request. Each archive should contain source files
+ plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads are
+ accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB`
+ for each uploaded and normalized source archive. The server records a shared
+ deployment batch ID for the resulting function deployments. Each function deployment runs its own
+ compile/publish workflow concurrently, and each publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB`
+ for the final container image.
+ One batch request can include up to 100 functions. Submit multiple batch requests for larger projects.
+ If one function fails before its workflow starts, already-started function deployments are left
+ running and the failed function is reported in the `failed` array. Failed new functions are deleted;
+ failed updates are rolled back to their previous metadata/status where possible.
+ operationId: createFunctionsBatch
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ functions:
+ type: string
+ description: JSON array of functions with `name`, `runtime`, optional `handler`, and `file_field`. Each `file_field` must name a multipart file field containing that function's ZIP or tar.gz source bundle.
+ code_0:
+ type: string
+ format: binary
+ description: Function ZIP or tar.gz archive referenced by the first manifest entry's `file_field`; additional code_N file fields may be included. Each archive is subject to SOURCE_ARCHIVE_SIZE_LIMIT_MB.
+ required:
+ - functions
+ responses:
+ '202':
+ description: Batch deployment accepted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchFunctionDeployResponse'
+ '207':
+ description: Batch deployment partially accepted; successful functions started deployment and failed functions were compensated where possible
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchFunctionDeployResponse'
+ '400':
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/schedulers:
+ get:
+ tags:
+ - Functions
+ summary: List every function scheduler in a project
+ description: |
+ Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`.
+ Returns schedulers across all functions in the project, ordered by
+ creation time descending, with standard page/limit pagination so
+ clients don't have to fan out one request per function.
+ operationId: listProjectSchedulers
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Project schedulers
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionSchedulerListResponse'
+ /projects/{id}/functions/{functionId}/schedulers:
+ get:
+ tags:
+ - Functions
+ summary: List schedulers for a function
+ operationId: listFunctionSchedulers
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ responses:
+ '200':
+ description: Function schedulers
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionSchedulerListResponse'
+ post:
+ tags:
+ - Functions
+ summary: Create a scheduler for a function
+ description: Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's deployed regions.
+ operationId: createFunctionScheduler
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateFunctionSchedulerRequest'
+ responses:
+ '201':
+ description: Scheduler created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionScheduler'
+ '400':
+ description: Invalid schedule or geofenced region
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/functions/{functionId}/schedulers/{schedulerId}:
+ get:
+ tags:
+ - Functions
+ summary: Get a function scheduler
+ operationId: getFunctionScheduler
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ - $ref: '#/components/parameters/SchedulerId'
+ responses:
+ '200':
+ description: Function scheduler
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionScheduler'
+ patch:
+ tags:
+ - Functions
+ summary: Update a function scheduler
+ operationId: updateFunctionScheduler
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ - $ref: '#/components/parameters/SchedulerId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateFunctionSchedulerRequest'
+ responses:
+ '200':
+ description: Scheduler updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionScheduler'
+ delete:
+ tags:
+ - Functions
+ summary: Delete a function scheduler
+ operationId: deleteFunctionScheduler
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ - $ref: '#/components/parameters/SchedulerId'
+ responses:
+ '204':
+ description: Scheduler deleted
+ /projects/{id}/functions/{functionId}/deployments:
+ get:
+ tags:
+ - Functions
+ summary: List function deployments
+ operationId: listFunctionDeployments
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FunctionId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedFunctionDeployments'
+ '404':
+ description: Function not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/frontends:
+ get:
+ tags:
+ - Frontends
+ summary: List all frontends in a project
+ description: |
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+ operationId: listFrontends
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedFrontends'
+ '400':
+ description: Bad request - invalid project identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ post:
+ tags:
+ - Frontends
+ summary: Create a new frontend deployment
+ description: |
+ Creates and deploys a frontend for the project.
+ If a frontend with the same name already exists in the project, this operation updates that
+ frontend using the uploaded archive and starts a new deployment. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. If another deployment is running, the response preserves the frontend's current status
+ and exposes the queued deployment through `pending_deployment_id`.
+ Existing frontend traffic continues to use an available runtime while the new deployment builds
+ and provisions. Each deployment publishes its own static assets before the runtimes switch to its
+ build, and the live build's assets keep serving until the new deployment is live, so a page loaded
+ mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes
+ back on the build they were running, leaves the frontend `active` on the previous deployment, and
+ records the attempted deployment as failed. `degraded` means the runtime remains available but
+ edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a
+ given frontend, while independent frontends and projects can deploy concurrently.
+ For monorepos, provide `app_root` as a relative path from the uploaded archive root
+ to the Next.js app that should be built. Omit it for single-app archives.
+ Supported frontend environments are Next.js 15.x and 16.x with Node.js
+ 22.x or 24.x. The Node.js runtime is inferred from
+ `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x.
+ The selected Node.js family must also satisfy the installed Next.js package's
+ `engines.node` constraint. Volcano tests Next 15.5.24 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.3 (`>=20.9.0`).
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container images are
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`).
+ Each project can contain up to 10,000 frontends regardless of plan.
+ operationId: createFrontend
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ required:
+ - name
+ - archive
+ properties:
+ name:
+ type: string
+ maxLength: 63
+ pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
+ description: DNS-safe frontend name
+ framework:
+ type: string
+ enum:
+ - nextjs
+ default: nextjs
+ description: Next.js frontend. Supported Next.js majors are 15.x and 16.x.
+ app_root:
+ type: string
+ maxLength: 1024
+ description: Optional relative POSIX path from the uploaded archive root to the Next.js app to build, for example `apps/web`.
+ example: apps/web
+ archive:
+ type: string
+ format: binary
+ description: ZIP or tar.gz archive of the frontend project directory or monorepo workspace root. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz archive.
+ responses:
+ '200':
+ description: Existing frontend updated; its deployment was started or queued
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Frontend'
+ '201':
+ description: Frontend created and deployment workflow started
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Frontend'
+ '400':
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Frontend deployment limit exceeded for the current plan or project hard cap
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Conflict - frontend deletion is queued or running
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Service unavailable - frontend workflow or archive limit configuration missing
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/frontends/{frontendId}:
+ get:
+ tags:
+ - Frontends
+ summary: Get frontend details
+ operationId: getFrontend
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Frontend'
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Frontends
+ summary: Delete a frontend
+ description: |
+ Schedules asynchronous frontend deletion. If another deployment is running, the frontend
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in frontend lists.
+ operationId: deleteFrontend
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ responses:
+ '202':
+ description: Frontend deletion started or queued
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Service unavailable - frontend workflow configuration missing
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/frontends/{frontendId}/redeploy:
+ post:
+ tags:
+ - Frontends
+ summary: Redeploy frontend using latest uploaded artifact
+ description: |
+ Starts a new frontend workflow using the latest stored artifact. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. An overlapping deployment preserves the frontend's current status, is exposed through
+ `pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its
+ published static assets remain available during provisioning, and a failed redeploy restores the
+ regional runtimes to that build and keeps it serving while the attempted deployment is recorded as
+ failed.
+ operationId: redeployFrontend
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ responses:
+ '200':
+ description: Frontend redeploy started or queued
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Frontend'
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Conflict - frontend deletion is queued or running
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Service unavailable - frontend workflow configuration missing
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/frontends/{frontendId}/domain:
+ get:
+ tags:
+ - Frontends
+ summary: Get frontend custom domain status
+ operationId: getFrontendCustomDomain
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ responses:
+ '200':
+ description: |
+ Frontend custom domain status, or null when the frontend has no
+ custom domain configured (the common empty state).
+ content:
+ application/json:
+ schema:
+ nullable: true
+ allOf:
+ - $ref: '#/components/schemas/FrontendCustomDomainResponse'
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ post:
+ tags:
+ - Frontends
+ summary: Configure frontend custom domain (PRO)
+ description: |
+ Configures one custom domain for a frontend.
+ The default Volcano-generated frontend URL remains active.
+ Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes.
+ operationId: createFrontendCustomDomain
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateFrontendCustomDomainRequest'
+ responses:
+ '200':
+ description: Custom domain already configured with same hostname
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FrontendCustomDomainResponse'
+ '201':
+ description: Custom domain provisioning started
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FrontendCustomDomainResponse'
+ '400':
+ description: Bad request - invalid domain
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - custom domains require PRO plan
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Conflict - custom domain already in use or frontend already has a custom domain
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Service unavailable - custom domain provisioning is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Frontends
+ summary: Delete frontend custom domain
+ operationId: deleteFrontendCustomDomain
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ responses:
+ '204':
+ description: Custom domain detach scheduled
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend or custom domain not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/frontends/{frontendId}/deployments:
+ get:
+ tags:
+ - Frontends
+ summary: List frontend deployments
+ operationId: listFrontendDeployments
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedFrontendDeployments'
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/frontends/{frontendId}/usage:
+ get:
+ tags:
+ - Frontends
+ summary: Per-day request and error counts for a single frontend
+ description: |
+ Returns a zero-filled daily series of request counts and 5xx
+ error counts for one frontend, oldest first. Each entry is one
+ UTC day; missing days (no traffic recorded) come back as
+ `requests: 0, errors: 0` so the response always has exactly
+ `days` entries.
+
+ Backs the Monitoring section on the Frontend detail page in
+ volcano-web. `days` defaults to 30 and is capped at 90 to keep
+ the (frontend_id, day) index scan bounded.
+ operationId: getFrontendUsageHistory
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/FrontendId'
+ - name: days
+ in: query
+ description: Number of trailing days to return (1–90, default 30).
+ required: false
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 90
+ default: 30
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FrontendUsageHistoryResponse'
+ '400':
+ description: Bad request - invalid identifier
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Forbidden - project ownership required
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Frontend not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/variables:
+ get:
+ tags:
+ - Variables
+ summary: List all variables for a project
+ description: |
+ Returns project-level environment variables used by deployed functions and frontends.
+ operationId: listVariables
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedVariables'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ post:
+ tags:
+ - Variables
+ summary: Create or update a variable
+ description: |
+ Creates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+ operationId: createVariable
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateVariableRequest'
+ responses:
+ '201':
+ description: Variable created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ '400':
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/databases:
+ get:
+ tags:
+ - Databases
+ summary: List all databases for a project
+ description: |
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit`. Cursor mode uses `cursor` and `limit`, supports `search`
+ (case-insensitive name match), and returns `next_cursor`/`prev_cursor`.
+ The optional `status` filter applies in both modes and is bound to the
+ cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400.
+ operationId: listDatabases
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedDatabases'
+ post:
+ tags:
+ - Databases
+ summary: Create a new serverless PostgreSQL database
+ description: |
+ Creates a serverless PostgreSQL database in the project.
+ Each project can contain up to 100 databases. Requests over this cap return 403.
+ operationId: createDatabase
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateDatabaseRequest'
+ responses:
+ '201':
+ description: Database created (provisioning)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Database'
+ '403':
+ description: Database limit exceeded for the project
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/databases/{databaseName}:
+ get:
+ tags:
+ - Databases
+ summary: Get database details
+ operationId: getDatabase
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Database'
+ delete:
+ tags:
+ - Databases
+ summary: Delete a database
+ description: |
+ Deletes a database and the instance backing it. When the instance is
+ removed synchronously the database row is deleted and the response is
+ `204`. If the instance cannot be deleted right away, the database row
+ is retained (status `deleting`) and its teardown is handed to the
+ background reconciler, which retries the deletion and removes the row
+ once the instance is gone; in that case the response is `202`. The database row is
+ never dropped while its instance still exists, so an instance is
+ never orphaned without a record to retry from.
+ operationId: deleteDatabase
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ responses:
+ '202':
+ description: |
+ Deletion accepted and in progress. The backing instance could not be
+ removed synchronously, so the database is marked `deleting` and torn
+ down asynchronously by the reconciler.
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ status:
+ type: string
+ example: deleting
+ message:
+ type: string
+ example: database deletion in progress
+ '204':
+ description: Database deleted (backing instance removed synchronously)
+ /projects/{id}/databases/{databaseName}/branches:
+ get:
+ tags:
+ - Database Branches
+ summary: List a database's branches
+ description: |
+ Returns every branch of the database, including those still provisioning
+ and those that failed, since each still holds a name.
+
+ Connection strings are omitted. Fetch a single branch to get its
+ connection string.
+ operationId: listDatabaseBranches
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseBranchList'
+ '404':
+ description: Project or database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Branching is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ post:
+ tags:
+ - Database Branches
+ summary: Create a branch of a database
+ description: |
+ Forks the database into a new branch. The branch starts as an exact copy
+ of the parent's data and diverges from there.
+
+ Provisioning is asynchronous: the response is `202` with the branch in
+ `provisioning` and no connection string. Poll the branch until it reports
+ `active`, at which point it carries its own connection string.
+
+ Retrying a create with a name that already exists returns `409` rather
+ than a second branch, so a retried request cannot silently consume two
+ slots of the branch allowance.
+ operationId: createDatabaseBranch
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateDatabaseBranchRequest'
+ responses:
+ '202':
+ description: Branch accepted and provisioning
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseBranch'
+ '400':
+ description: Invalid branch name or lifetime
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: |
+ The database has reached its branch allowance, or the owner's plan
+ does not include branching.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project or database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: |
+ A branch of that name already exists on this database, or the
+ database cannot be branched right now because it is still
+ provisioning, failed, or being deleted.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Branching is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/databases/{databaseName}/branches/{branchName}:
+ get:
+ tags:
+ - Database Branches
+ summary: Get a branch
+ description: |
+ Returns the branch, including its connection string once it is `active`.
+ Poll this after creating a branch to learn when it is connectable.
+ operationId: getDatabaseBranch
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseBranch'
+ '404':
+ description: Project, database, or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Branching is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ patch:
+ tags:
+ - Database Branches
+ summary: Extend a branch's lifetime
+ description: |
+ Replaces the branch's lifetime and restarts the countdown from now, so a
+ branch you are still working on is not swept mid-session. The new
+ duration is remembered, so a later reset re-arms the same lifetime.
+ operationId: updateDatabaseBranch
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateDatabaseBranchRequest'
+ responses:
+ '200':
+ description: Lifetime updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseBranch'
+ '400':
+ description: Requested lifetime is outside the allowed range
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project, database, or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: The branch is being deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Branching is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Database Branches
+ summary: Delete a branch
+ description: |
+ Marks the branch for teardown and returns immediately. The branch stops
+ accepting connections at once; its fork and its row are removed by a
+ background job, so a provider outage cannot leave the call hanging or the
+ branch half-deleted.
+
+ Deleting a branch that is still provisioning is allowed and stops the
+ build, and repeating the call while teardown is in progress is accepted
+ again. Once the branch is gone the call returns `404`.
+ operationId: deleteDatabaseBranch
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ responses:
+ '202':
+ description: Deletion accepted and in progress
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ status:
+ type: string
+ example: deleting
+ message:
+ type: string
+ example: branch deletion in progress
+ required:
+ - status
+ - message
+ '404':
+ description: Project, database, or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Branching is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/databases/{databaseName}/branches/{branchName}/reset:
+ post:
+ tags:
+ - Database Branches
+ summary: Reset a branch to its parent's current state
+ description: |
+ Discards everything written on the branch and re-forks it from the
+ parent as it is now.
+
+ Returns immediately with the branch in `provisioning`. The rewind runs in
+ the background; poll the branch until it reports `active` before
+ connecting again.
+
+ The branch keeps its name and its connection string, so anything holding
+ that string keeps working once it is active again, and its lifetime is
+ re-armed to the duration it was created with. The branch does not serve
+ connections for the duration of the reset.
+ operationId: resetDatabaseBranch
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ responses:
+ '202':
+ description: Branch reset accepted; the branch is provisioning
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseBranch'
+ '404':
+ description: Project, database, or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: |
+ The branch is not active, or a reset is already in progress.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Branching is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/databases/{databaseName}/branches/{branchName}/reset-password:
+ post:
+ tags:
+ - Database Branches
+ summary: Rotate a branch's password
+ description: |
+ Issues a new password for the branch and invalidates the previous
+ connection string. Existing connections are not interrupted; new ones
+ must use the returned string.
+
+ The parent database's credentials are untouched.
+ operationId: resetDatabaseBranchPassword
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ responses:
+ '200':
+ description: Password rotated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseBranch'
+ '404':
+ description: Project, database, or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: The branch is not active
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Branching is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/databases/{databaseName}/reset-password:
+ post:
+ tags:
+ - Databases
+ summary: Reset database password
+ description: |
+ Rotates the Volcano-managed PostgreSQL password used by clients when connecting
+ through pgproxy. This does not rotate or expose the internal owner password.
+ The returned password and connection string are the only client credentials that
+ will authenticate through pgproxy after reset.
+ operationId: resetDatabasePassword
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ responses:
+ '200':
+ description: Password reset successful
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ role_name:
+ type: string
+ description: Volcano-managed per-database client login (also the pgproxy routing username)
+ example: volcano_client_11111111-1111-1111-1111-111111111111
+ new_password:
+ type: string
+ description: New Volcano-managed client password. Always starts with `vpg_`.
+ connection_string:
+ type: string
+ description: Updated pgproxy connection string using Volcano-managed credentials.
+ /projects/{id}/databases/{databaseName}/type:
+ patch:
+ tags:
+ - Databases
+ summary: Update database size
+ description: |
+ Change the size tier of a database. This may briefly interrupt active connections.
+
+ **Available sizes:**
+ - `volcano-db-xs`: Up to ~1GB RAM - Development, small apps
+ - `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic
+ - `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications
+ - `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets
+ - `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads
+ - `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale
+ operationId: updateDatabaseType
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateDatabaseTypeRequest'
+ responses:
+ '200':
+ description: Database type updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Database'
+ '400':
+ description: Invalid database type
+ '404':
+ description: Database not found
+ /projects/{id}/databases/{databaseName}/stats:
+ get:
+ tags:
+ - Databases
+ summary: Get database consumption metrics
+ description: |
+ Retrieve consumption metrics including storage, compute time, and data transfer.
+ Metrics are aggregated at the project level. Defaults to last 24 hours.
+
+ **Note:** Advanced metrics require an upgraded plan.
+ operationId: getDatabaseStats
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/DatabaseName'
+ - name: from
+ in: query
+ required: false
+ schema:
+ type: string
+ format: date-time
+ description: Start time in RFC3339 format (e.g., "2024-01-01T00:00:00Z"). Defaults to 24 hours ago.
+ - name: to
+ in: query
+ required: false
+ schema:
+ type: string
+ format: date-time
+ description: End time in RFC3339 format (e.g., "2024-01-02T00:00:00Z"). Defaults to now.
+ - name: granularity
+ in: query
+ required: false
+ schema:
+ type: string
+ enum:
+ - hourly
+ - daily
+ - monthly
+ default: hourly
+ description: Level of detail for metrics aggregation
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseStats'
+ '400':
+ description: Invalid parameters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Database metrics not available or requires upgraded plan
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /databases/{databaseName}/query/ping:
+ post:
+ tags:
+ - Database Queries
+ summary: Database connectivity probe (REST API)
+ description: |
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+ operationId: queryDatabasePing
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ responses:
+ '200':
+ description: Database is reachable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - '?column?': 1
+ count: 1
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/query/select:
+ post:
+ tags:
+ - Database Queries
+ summary: Query database with SELECT (REST API)
+ description: |
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use functions with direct SQL
+ operationId: queryDatabaseSelect
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseSelectRequest'
+ responses:
+ '200':
+ description: Query successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: uuid-123
+ title: My Post
+ content: Post content
+ status: published
+ views: 150
+ created_at: '2026-01-13T10:00:00Z'
+ count: 1
+ '400':
+ description: Invalid query
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/query/insert:
+ post:
+ tags:
+ - Database Queries
+ summary: Insert data into database (REST API)
+ description: |
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+ operationId: queryDatabaseInsert
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseInsertRequest'
+ responses:
+ '200':
+ description: Insert successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: uuid-123
+ title: My New Post
+ content: This is the content
+ status: draft
+ user_id: user-uuid
+ created_at: '2026-01-13T10:00:00Z'
+ count: 1
+ '400':
+ description: Invalid request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/query/update:
+ post:
+ tags:
+ - Database Queries
+ summary: Update data in database (REST API)
+ description: |
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+ operationId: queryDatabaseUpdate
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseUpdateRequest'
+ responses:
+ '200':
+ description: Update successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: post-uuid
+ title: Updated Title
+ status: published
+ updated_at: '2026-01-13T10:05:00Z'
+ count: 1
+ '400':
+ description: Invalid request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/query/delete:
+ post:
+ tags:
+ - Database Queries
+ summary: Delete data from database (REST API)
+ description: |
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+ operationId: queryDatabaseDelete
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseDeleteRequest'
+ responses:
+ '200':
+ description: Delete successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: post-uuid
+ title: Deleted Post
+ count: 1
+ '400':
+ description: Invalid request or missing filters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/branches/{branchName}/query/ping:
+ post:
+ tags:
+ - Database Queries
+ summary: Database connectivity probe (REST API)
+ description: |
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+ operationId: queryDatabaseBranchPing
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ responses:
+ '200':
+ description: Database is reachable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - '?column?': 1
+ count: 1
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/branches/{branchName}/query/select:
+ post:
+ tags:
+ - Database Queries
+ summary: Query database with SELECT (REST API)
+ description: |
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+ operationId: queryDatabaseBranchSelect
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseSelectRequest'
+ responses:
+ '200':
+ description: Query successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: uuid-123
+ title: My Post
+ content: Post content
+ status: published
+ views: 150
+ created_at: '2026-01-13T10:00:00Z'
+ count: 1
+ '400':
+ description: Invalid query
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/branches/{branchName}/query/insert:
+ post:
+ tags:
+ - Database Queries
+ summary: Insert data into database (REST API)
+ description: |
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+ operationId: queryDatabaseBranchInsert
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseInsertRequest'
+ responses:
+ '200':
+ description: Insert successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: uuid-123
+ title: My New Post
+ content: This is the content
+ status: draft
+ user_id: user-uuid
+ created_at: '2026-01-13T10:00:00Z'
+ count: 1
+ '400':
+ description: Invalid request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/branches/{branchName}/query/update:
+ post:
+ tags:
+ - Database Queries
+ summary: Update data in database (REST API)
+ description: |
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+ operationId: queryDatabaseBranchUpdate
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseUpdateRequest'
+ responses:
+ '200':
+ description: Update successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: post-uuid
+ title: Updated Title
+ status: published
+ updated_at: '2026-01-13T10:05:00Z'
+ count: 1
+ '400':
+ description: Invalid request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/{databaseName}/branches/{branchName}/query/delete:
+ post:
+ tags:
+ - Database Queries
+ summary: Delete data from database (REST API)
+ description: |
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+ operationId: queryDatabaseBranchDelete
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/DatabaseName'
+ - $ref: '#/components/parameters/BranchName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseDeleteRequest'
+ responses:
+ '200':
+ description: Delete successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatabaseQueryResult'
+ example:
+ data:
+ - id: post-uuid
+ title: Deleted Post
+ count: 1
+ '400':
+ description: Invalid request or missing filters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Database or branch not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ $ref: '#/components/responses/DatabaseQueryCapExceeded'
+ /databases/regions:
+ get:
+ tags:
+ - Databases
+ summary: List platform-supported regions for database provisioning
+ operationId: listDatabaseRegions
+ description: |
+ Returns the regions enabled for database provisioning in this platform environment.
+ This is a public endpoint that doesn't require authentication.
+ responses:
+ '200':
+ description: List of platform-supported regions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ id:
+ type: string
+ example: aws-us-east-1
+ description: Region identifier for API usage
+ name:
+ type: string
+ example: AWS US East 1 (N. Virginia)
+ description: Human-readable region name
+ /databases/postgres-versions:
+ get:
+ tags:
+ - Databases
+ summary: List available PostgreSQL versions
+ operationId: listPostgresVersions
+ description: |
+ Returns a list of supported PostgreSQL major versions for database provisioning.
+ This is a public endpoint that doesn't require authentication.
+ responses:
+ '200':
+ description: List of available PostgreSQL versions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ version:
+ type: string
+ example: '16'
+ description: PostgreSQL major version number
+ name:
+ type: string
+ example: PostgreSQL 16
+ description: Human-readable version name
+ default:
+ type: boolean
+ description: Whether this is the default version (recommended)
+ deprecated:
+ type: boolean
+ description: Whether this version is deprecated (approaching EOL)
+ /functions/runtimes:
+ get:
+ tags:
+ - Functions
+ summary: List supported function runtimes
+ operationId: listFunctionRuntimes
+ security: []
+ description: |
+ Returns the public function runtime catalog used by CLI clients to select supported runtimes,
+ language defaults, and local source packaging metadata for deployments.
+ This is a public endpoint that doesn't require authentication.
+ responses:
+ '200':
+ description: Supported function runtimes
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FunctionRuntimesResponse'
+ /functions/regions:
+ get:
+ tags:
+ - Functions
+ summary: List available regions for function deployment
+ operationId: listFunctionRegions
+ security: []
+ description: |
+ Returns the configured regions where functions can be deployed, each annotated
+ with a human-readable label and country flag emoji for use in UI pickers.
+ This is a public endpoint that doesn't require authentication.
+ responses:
+ '200':
+ description: Available function deployment regions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/FunctionRegion'
+ /projects/{id}/variables/{name}:
+ get:
+ tags:
+ - Variables
+ summary: Get variable by name
+ description: |
+ Returns a project-level environment variable used by deployed functions and frontends.
+ operationId: getVariable
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/VariableName'
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ '404':
+ description: Variable not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ put:
+ tags:
+ - Variables
+ summary: Update a variable
+ description: |
+ Updates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+ operationId: updateVariable
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/VariableName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateVariableRequest'
+ responses:
+ '200':
+ description: Variable updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ '404':
+ description: Variable not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Variables
+ summary: Delete a variable
+ description: |
+ Deletes a project-level environment variable and triggers asynchronous propagation
+ of the removal to deployed functions and frontends in the project's configured regions.
+ operationId: deleteVariable
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/VariableName'
+ responses:
+ '204':
+ description: Variable deleted
+ '404':
+ description: Variable not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/password-policy:
+ get:
+ tags:
+ - Authentication
+ summary: Get the effective password policy
+ description: |
+ Returns the backend-enforced password bounds and compromised-password
+ screening status for the project identified by the anon key. A valid
+ anon key is required, but no route-specific auth permission is needed.
+ operationId: authGetPasswordPolicy
+ security:
+ - AnonKey: []
+ responses:
+ '200':
+ description: Effective password policy
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthPasswordPolicy'
+ '401':
+ description: Invalid, missing, or revoked anon key
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project or auth configuration not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/signup:
+ post:
+ tags:
+ - Authentication
+ summary: Sign up a new auth user
+ description: |
+ Create a new end-user account. The project is determined from the anon key.
+ Requires project-specific anon key in Authorization header.
+
+ **Session-less**: signup never issues a session. On success it returns a
+ uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client
+ obtains a session with a subsequent `POST /auth/signin`. If email confirmation
+ is enabled for the project, a confirmation email is sent and
+ `confirmation_required` is `true`.
+
+ **Anti-enumeration**: a signup for an already-registered email returns the
+ exact same `201` response as a fresh signup — it never returns `409` — so the
+ response cannot be used to discover which emails are registered.
+ operationId: authSignup
+ security:
+ - AnonKey: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email
+ - password
+ properties:
+ email:
+ type: string
+ format: email
+ password:
+ type: string
+ description: |
+ Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ user_metadata:
+ type: object
+ additionalProperties: true
+ responses:
+ '201':
+ description: |
+ Signup acknowledged (session-less). Returned identically for a new
+ account and for an already-registered email (anti-enumeration).
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthSignupResponse'
+ '400':
+ description: Invalid input (bad email/password format)
+ '401':
+ description: |
+ Unauthorized - Invalid, tampered, revoked, or wrong-project anon key
+ '403':
+ description: |
+ Forbidden - Signups disabled, anon key lacks signup permission, or the
+ email domain is not in `allowed_email_domains`. The internal
+ `anonymous.volcano.internal` domain is reserved for anonymous
+ accounts and is refused whatever the project allows.
+ '429':
+ description: Rate limit exceeded
+ '503':
+ description: Compromised-password screening is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/signin:
+ post:
+ tags:
+ - Authentication
+ summary: Sign in an auth user
+ description: |
+ Authenticate with email and password. Requires an anon key.
+
+ Set `session_mode` to `cookie` to request HttpOnly refresh-token
+ storage. Cookie mode is honored only for an exact, credentialed CORS
+ origin on the same schemeful site as this API. Otherwise the response
+ retains the refresh token in its body.
+ operationId: authSignin
+ security:
+ - AnonKey: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email
+ - password
+ properties:
+ email:
+ type: string
+ password:
+ type: string
+ session_mode:
+ type: string
+ enum:
+ - cookie
+ responses:
+ '200':
+ description: Signin successful
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthTokenResponse'
+ '400':
+ description: Invalid input (missing email/password)
+ '401':
+ description: |
+ Unauthorized - Invalid credentials, invalid/tampered/revoked anon key,
+ or account banned/deleted
+ '403':
+ description: |
+ Forbidden - Anon key lacks signin permission, or the email domain is
+ not in `allowed_email_domains` while `allowed_email_domains_mode` is
+ `signup_and_signin`. The domain is taken from the account's canonical
+ email (its primary identity), which is not necessarily the address in
+ the request.
+ '429':
+ description: Rate limit exceeded
+ /auth/refresh:
+ post:
+ tags:
+ - Authentication
+ summary: Refresh access token
+ description: |
+ Get a new access token using a refresh token. Requires an anon key.
+
+ Send `refresh_token` in the body for the default flow. An eligible
+ cookie-mode browser request may instead send `session_mode: cookie`
+ with an empty token or omit the request body; the API reads and resets
+ the project's HttpOnly cookie and omits `refresh_token` from the
+ response.
+ operationId: authRefresh
+ security:
+ - AnonKey: []
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ refresh_token:
+ type: string
+ session_mode:
+ type: string
+ enum:
+ - cookie
+ responses:
+ '200':
+ description: Token refreshed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthTokenResponse'
+ '401':
+ description: Invalid or expired refresh token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: |
+ The account's email domain is not in `allowed_email_domains` while
+ `allowed_email_domains_mode` is `signup_and_signin`, so the session
+ cannot be extended
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Rate limit exceeded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/logout:
+ post:
+ tags:
+ - Authentication
+ summary: Logout (revoke refresh token)
+ description: |
+ Invalidate a refresh token. Requires an anon key.
+
+ Send `refresh_token` for the default flow. An eligible cookie-mode
+ browser request may instead send `session_mode: cookie` with an empty
+ token; logout remains idempotent when the cookie is missing or expired.
+ operationId: authLogout
+ security:
+ - AnonKey: []
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ refresh_token:
+ type: string
+ session_mode:
+ type: string
+ enum:
+ - cookie
+ responses:
+ '204':
+ description: Logged out successfully
+ /auth/forgot-password:
+ post:
+ tags:
+ - Authentication
+ summary: Request password reset
+ description: |
+ Generates recovery token and stores it (email sending pending).
+ Returns generic message to prevent email enumeration.
+ Project is identified via the anon key.
+ operationId: authForgotPassword
+ security:
+ - AnonKey: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email
+ properties:
+ email:
+ type: string
+ format: email
+ responses:
+ '200':
+ description: Generic success message (doesn't reveal if email exists)
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ example: If the email exists, a password reset link has been sent
+ '403':
+ description: Password reset is disabled for this project
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Rate limit exceeded (10 requests per hour per IP)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/reset-password:
+ post:
+ tags:
+ - Authentication
+ summary: Reset password with recovery token
+ description: |
+ Reset password using recovery token from forgot-password.
+ Revokes all existing sessions for security.
+ operationId: authResetPassword
+ security:
+ - AnonKey: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - token
+ - new_password
+ properties:
+ token:
+ type: string
+ description: Recovery token from forgot-password
+ new_password:
+ type: string
+ description: |
+ Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ responses:
+ '200':
+ description: Password reset successful
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ '400':
+ description: Password doesn't meet requirements
+ '401':
+ description: Invalid or expired token
+ '503':
+ description: Compromised-password screening is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/confirm:
+ post:
+ tags:
+ - Authentication
+ summary: Confirm email address
+ description: |
+ Confirm email address using token sent via email.
+ Required if require_email_confirmation is enabled.
+ operationId: authConfirmEmail
+ security:
+ - AnonKey: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - token
+ properties:
+ token:
+ type: string
+ description: Confirmation token from email
+ responses:
+ '200':
+ description: Email confirmed or already confirmed
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ enum:
+ - Email confirmed successfully
+ - Email already confirmed
+ examples:
+ confirmed:
+ summary: Fresh confirmation
+ value:
+ message: Email confirmed successfully
+ alreadyConfirmed:
+ summary: Token belongs to already-confirmed user
+ value:
+ message: Email already confirmed
+ '400':
+ description: Missing confirmation token in request body
+ '401':
+ description: Invalid or expired token
+ /auth/resend-confirmation:
+ post:
+ tags:
+ - Authentication
+ summary: Resend confirmation email
+ description: |
+ Resend email confirmation link.
+ Returns generic message to prevent email enumeration.
+ No email is sent when the account does not exist or is already confirmed.
+ If the account exists and is unconfirmed, a new token is generated and
+ any previous confirmation token is invalidated.
+ operationId: authResendConfirmation
+ security:
+ - AnonKey: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email
+ properties:
+ email:
+ type: string
+ format: email
+ responses:
+ '200':
+ description: Generic success message
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ '429':
+ description: Rate limit exceeded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/signup-anonymous:
+ post:
+ tags:
+ - Authentication
+ summary: Create anonymous user
+ description: |
+ Create guest user without email/password.
+
+ User metadata (like display_name) can be included and will appear in realtime presence events.
+ Requires enable_anonymous_signins to be true.
+ operationId: authSignupAnonymous
+ security:
+ - AnonKey: []
+ requestBody:
+ description: Optional user metadata
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user_metadata:
+ type: object
+ additionalProperties: true
+ description: Custom user metadata (e.g., display_name, avatar_url)
+ example:
+ display_name: Alice
+ avatar_url: https://example.com/alice.jpg
+ responses:
+ '201':
+ description: Anonymous user created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthTokenResponse'
+ '403':
+ description: Anonymous signins disabled
+ /auth/user/convert-anonymous:
+ post:
+ tags:
+ - Authentication
+ summary: Convert anonymous user to authenticated
+ description: |
+ Add email and password to anonymous user.
+ Requires auth user access token.
+ If require_email_confirmation is enabled for the project, the converted
+ user remains unconfirmed until /auth/confirm succeeds. When email
+ sending is enabled, a confirmation email is sent during conversion.
+ operationId: authConvertAnonymous
+ security:
+ - AuthUserAccessToken: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email
+ - password
+ properties:
+ email:
+ type: string
+ format: email
+ password:
+ type: string
+ description: |
+ Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ user_metadata:
+ type: object
+ additionalProperties: true
+ responses:
+ '200':
+ description: User converted successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ $ref: '#/components/schemas/AuthUser'
+ '400':
+ description: Not an anonymous user
+ '403':
+ description: |
+ The chosen email domain is not in `allowed_email_domains`
+ '409':
+ description: Email already in use
+ '503':
+ description: Compromised-password screening is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/change-email:
+ post:
+ tags:
+ - Authentication
+ summary: Request email change
+ description: |
+ Request to change user's email address.
+ Sends confirmation token to new email address.
+ operationId: authRequestEmailChange
+ security:
+ - AuthUserAccessToken: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - new_email
+ properties:
+ new_email:
+ type: string
+ format: email
+ responses:
+ '200':
+ description: Confirmation email sent
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ new_email:
+ type: string
+ '400':
+ description: Invalid email format or same as current email
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: |
+ The requested email domain is not in `allowed_email_domains`
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Email already in use
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Rate limit exceeded (10 requests per hour per IP)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/confirm-email-change:
+ post:
+ tags:
+ - Authentication
+ summary: Confirm email change
+ description: Confirm email change with token sent to new address
+ operationId: authConfirmEmailChange
+ security:
+ - AuthUserAccessToken: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email_change_token
+ properties:
+ email_change_token:
+ type: string
+ responses:
+ '200':
+ description: Email changed successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ user:
+ $ref: '#/components/schemas/AuthUser'
+ '400':
+ description: Invalid or expired token, or no pending email change
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: |
+ The pending email domain is no longer in `allowed_email_domains`.
+ Re-checked here because the allowlist can narrow between the request
+ and the confirmation.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Email is now in use by another user
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/cancel-email-change:
+ delete:
+ tags:
+ - Authentication
+ summary: Cancel pending email change
+ operationId: authCancelEmailChange
+ security:
+ - AuthUserAccessToken: []
+ responses:
+ '200':
+ description: Email change cancelled
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/sessions:
+ get:
+ tags:
+ - Authentication
+ summary: Get current user's sessions
+ description: |
+ Returns paginated sessions for the currently authenticated user.
+ Each session includes device info, IP addresses, and activity timestamps.
+ The current session is marked with `is_current: true`.
+
+ **Ordering and pagination.** Without `sort`, results are ordered by most
+ recent activity and paged with `page`/`limit`, returning the
+ `sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the
+ legacy default and is preserved for existing clients.
+
+ Send `sort=created_at` to opt into the standard list contract: results are
+ ordered by session start (newest first) and may be paged either with
+ `page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded
+ `offset` past the cursor anchor. Cursor responses use the shared
+ `data` envelope with `next_cursor`/`prev_cursor`.
+
+ Unlike other list endpoints, sending `limit` without `page` does **not**
+ select cursor mode here; `sort=created_at` is the only opt-in. Cursor
+ pagination is rejected with 400 for the activity order, because
+ `last_activity_at` changes whenever a session refreshes its token: a row
+ that crosses the cursor anchor between two requests would be skipped and
+ never shown. The `status=expired` filter is also offset-only because a
+ session can expire above the cursor anchor during a walk. Sending that
+ filter in cursor mode, `page` with `cursor` or `ending_before`, or both
+ cursor directions returns 400.
+ operationId: authGetMySessions
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Page number (1-indexed)
+ schema:
+ type: integer
+ minimum: 1
+ default: 1
+ - name: limit
+ in: query
+ description: Number of sessions per page (max 100)
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 20
+ - name: sort
+ in: query
+ description: |
+ Sort key. `last_activity` (default) orders by most recent activity and
+ supports offset pagination only. `created_at` orders by session start
+ and supports both offset and cursor pagination.
+ schema:
+ type: string
+ enum:
+ - last_activity
+ - created_at
+ default: last_activity
+ - name: status
+ in: query
+ description: |
+ Filter by whether the session can still be refreshed. Omit for every
+ stored session, including expired ones. `expired` is not supported
+ with cursor pagination.
+ schema:
+ type: string
+ enum:
+ - active
+ - expired
+ - name: cursor
+ in: query
+ description: |
+ Opaque keyset cursor from a previous response's `next_cursor`. Requires
+ `sort=created_at`; mutually exclusive with `page` and `ending_before`.
+ schema:
+ type: string
+ - name: ending_before
+ in: query
+ description: |
+ Opaque keyset cursor from a previous response's `prev_cursor`, paging
+ backward. Requires `sort=created_at`; mutually exclusive with `page`
+ and `cursor`.
+ schema:
+ type: string
+ - name: offset
+ in: query
+ description: |
+ Bounded number of rows to skip past the cursor anchor (the hybrid
+ jump, maximum 100000). Ignored unless `cursor` or `ending_before` is
+ supplied.
+ schema:
+ type: integer
+ minimum: 0
+ maximum: 100000
+ responses:
+ '200':
+ description: Paginated list of user sessions
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ sessions:
+ type: array
+ items:
+ $ref: '#/components/schemas/AuthSession'
+ total:
+ type: integer
+ description: Total number of sessions
+ page:
+ type: integer
+ description: Current page number
+ limit:
+ type: integer
+ description: Number of sessions per page
+ total_pages:
+ type: integer
+ description: Total number of pages
+ data:
+ type: array
+ description: Sessions for this page (cursor pagination only)
+ items:
+ $ref: '#/components/schemas/AuthSession'
+ has_more:
+ type: boolean
+ description: Whether a further page exists (cursor pagination only)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
+ '400':
+ description: Invalid or conflicting pagination parameters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Authentication
+ summary: Sign out from all other devices
+ description: |
+ Deletes all sessions except the current one.
+ Use this to log out from all other devices while keeping the current session active.
+ operationId: authDeleteAllMySessions
+ security:
+ - AuthUserAccessToken: []
+ responses:
+ '204':
+ description: All other sessions deleted
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/sessions/{sessionId}:
+ delete:
+ tags:
+ - Authentication
+ summary: Sign out from specific device
+ description: |
+ Deletes a specific session, logging out that device.
+ You can get session IDs from the list sessions endpoint.
+ operationId: authDeleteMySession
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: sessionId
+ in: path
+ required: true
+ description: The session ID to delete
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Session deleted
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Session not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user:
+ get:
+ tags:
+ - Authentication
+ summary: Get current user profile
+ description: Returns authenticated user's profile. Requires access token.
+ operationId: authGetUser
+ security:
+ - AuthUserAccessToken: []
+ responses:
+ '200':
+ description: User profile
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ $ref: '#/components/schemas/AuthUser'
+ '401':
+ description: Not authenticated - access token missing or invalid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ put:
+ tags:
+ - Authentication
+ summary: Update user profile
+ description: Update password or metadata. Requires access token.
+ operationId: authUpdateUser
+ security:
+ - AuthUserAccessToken: []
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ password:
+ type: string
+ description: |
+ Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ user_metadata:
+ type: object
+ additionalProperties: true
+ description: |
+ Metadata keys to merge into the current user metadata.
+ Omitted keys remain unchanged; set a key to null to remove it.
+ Merging is shallow; nested objects replace the stored value for that top-level key.
+ responses:
+ '200':
+ description: Profile updated
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ $ref: '#/components/schemas/AuthUser'
+ '400':
+ description: Bad request - invalid password or metadata format
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated - access token missing or invalid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Compromised-password screening is temporarily unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/identities:
+ get:
+ tags:
+ - Authentication
+ summary: List the current user's identities
+ description: |
+ Returns every real email identity the account owns. An account can own
+ multiple identities (for example a password identity plus one or more
+ OAuth identities on different emails). Anonymous accounts have no real
+ identity and return an empty list.
+ operationId: authListIdentities
+ security:
+ - AuthUserAccessToken: []
+ responses:
+ '200':
+ description: List of identities
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthIdentitiesResponse'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/identities/{identityId}:
+ delete:
+ tags:
+ - Authentication
+ summary: Unlink an identity from the current user
+ description: |
+ Removes a non-primary identity and its attached sign-in methods. Refused
+ when the identity is the account's primary, its only identity, or when
+ removing it would leave the account with no way to sign in.
+ operationId: authUnlinkIdentity
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: identityId
+ in: path
+ required: true
+ description: The identity ID to unlink
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Identity unlinked
+ '400':
+ description: Identity cannot be unlinked (primary, last, or would remove last sign-in method), or the identity id is malformed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Identity not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/methods:
+ get:
+ tags:
+ - Authentication
+ summary: List the current user's sign-in methods
+ description: |
+ Returns a flat list of every sign-in method the account owns (password,
+ each OAuth provider, and any active anonymous method), with the primary
+ method flagged. Password stubs and converted anonymous methods are excluded.
+ operationId: authListMethods
+ security:
+ - AuthUserAccessToken: []
+ responses:
+ '200':
+ description: List of sign-in methods
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthMethodsResponse'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/user/methods/{methodId}/promote:
+ post:
+ tags:
+ - Authentication
+ summary: Set a method as the account's primary
+ description: |
+ Promotes the given method to the account's primary sign-in method. The
+ account's canonical email is re-derived from the promoted method's identity.
+ Refused for password stubs and converted anonymous methods, and for an
+ identity whose domain is outside the project's `allowed_email_domains`.
+ operationId: authPromoteMethod
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: methodId
+ in: path
+ required: true
+ description: The method ID to promote
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: The promoted method
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthMethodSummary'
+ '400':
+ description: This method cannot be set as primary (password stub, converted anonymous method, or unverified email), or the method id is malformed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: The promoted identity's email domain is not in the project's allowed_email_domains
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Method not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/auth/insights:
+ get:
+ tags:
+ - Auth Admin
+ summary: Get auth user insights
+ description: |
+ Returns current auth-user totals, rolling 30-day active users, and
+ zero-filled signup and successful sign-in counts for an inclusive UTC
+ date range. Weeks start on Monday. Sign-in counts and active-user
+ activity begin when collection is deployed. Historical signup counts
+ are backfilled from users present at deployment. Token refreshes affect
+ active users but not the sign-in series.
+ operationId: getAuthInsights
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: from
+ in: query
+ description: Inclusive UTC start date. Defaults to 29 days before `to`.
+ schema:
+ type: string
+ format: date
+ - name: to
+ in: query
+ description: Inclusive UTC end date. Defaults to today.
+ schema:
+ type: string
+ format: date
+ - name: interval
+ in: query
+ description: Chart bucket size. Defaults to `day`.
+ schema:
+ $ref: '#/components/schemas/AuthInsightsInterval'
+ responses:
+ '200':
+ description: Auth insights retrieved
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthInsightsResponse'
+ example:
+ project_id: 4f165080-a931-4e03-b3bd-41c45c3f0058
+ observed_at: '2026-07-20T18:00:00Z'
+ window:
+ from: '2026-06-21'
+ to: '2026-07-20'
+ interval: day
+ summary:
+ total_users: 1234
+ active_users_30d: 418
+ series:
+ - bucket_start: '2026-07-20'
+ signups: 12
+ signins: 97
+ is_partial: true
+ '400':
+ description: Invalid date range or interval
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized - invalid or missing token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Access denied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/auth/users:
+ get:
+ tags:
+ - Auth Admin
+ summary: List all auth users (admin)
+ description: List auth users in project. Requires platform token.
+ operationId: listAuthUsers
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ - name: status
+ in: query
+ required: false
+ description: Filter by effective status. `banned` returns only currently-banned users; an expired temporary ban lists as `active`.
+ schema:
+ type: string
+ enum:
+ - active
+ - banned
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedAuthUsers'
+ '400':
+ description: Invalid status or pagination parameters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/auth/users/{userId}:
+ get:
+ tags:
+ - Auth Admin
+ summary: Get specific auth user (admin)
+ operationId: getAuthUser
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: userId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Auth user details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthUser'
+ delete:
+ tags:
+ - Auth Admin
+ summary: Delete auth user (admin)
+ description: Soft-deletes user and revokes all sessions
+ operationId: deleteAuthUser
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: userId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: User deleted
+ /projects/{id}/auth/users/{userId}/sessions:
+ get:
+ tags:
+ - Auth Admin
+ summary: List user sessions
+ description: |
+ List paginated sessions for a specific auth user.
+ Returns session details including device info, IP address, and activity timestamps.
+
+ Ordering and pagination match `GET /auth/user/sessions`: the default is
+ activity order with `page`/`limit` and the legacy `sessions` body, and
+ `sort=created_at` opts into the standard cursor/offset hybrid with the
+ shared `data` envelope. Cursor pagination is only available for
+ `sort=created_at`, because the activity timestamp changes under paging.
+ The `status=expired` filter is offset-only because sessions can expire
+ above a cursor anchor during a walk.
+ operationId: listUserSessions
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: userId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ - name: page
+ in: query
+ description: Page number (1-indexed)
+ schema:
+ type: integer
+ minimum: 1
+ default: 1
+ - name: limit
+ in: query
+ description: Number of sessions per page (max 100)
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 20
+ - name: sort
+ in: query
+ description: |
+ Sort key. `last_activity` (default) orders by most recent activity and
+ supports offset pagination only. `created_at` orders by session start
+ and supports both offset and cursor pagination.
+ schema:
+ type: string
+ enum:
+ - last_activity
+ - created_at
+ default: last_activity
+ - name: status
+ in: query
+ description: |
+ Filter by whether the session can still be refreshed. Omit for every
+ stored session, including expired ones. `expired` is not supported
+ with cursor pagination.
+ schema:
+ type: string
+ enum:
+ - active
+ - expired
+ - name: cursor
+ in: query
+ description: |
+ Opaque keyset cursor from a previous response's `next_cursor`. Requires
+ `sort=created_at`; mutually exclusive with `page` and `ending_before`.
+ schema:
+ type: string
+ - name: ending_before
+ in: query
+ description: |
+ Opaque keyset cursor from a previous response's `prev_cursor`, paging
+ backward. Requires `sort=created_at`; mutually exclusive with `page`
+ and `cursor`.
+ schema:
+ type: string
+ - name: offset
+ in: query
+ description: |
+ Bounded number of rows to skip past the cursor anchor (the hybrid
+ jump, maximum 100000). Ignored unless `cursor` or `ending_before` is
+ supplied.
+ schema:
+ type: integer
+ minimum: 0
+ maximum: 100000
+ responses:
+ '200':
+ description: Paginated list of user sessions
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ sessions:
+ type: array
+ items:
+ $ref: '#/components/schemas/AuthSession'
+ total:
+ type: integer
+ description: Total number of sessions
+ page:
+ type: integer
+ description: Current page number
+ limit:
+ type: integer
+ description: Number of sessions per page
+ total_pages:
+ type: integer
+ description: Total number of pages
+ data:
+ type: array
+ description: Sessions for this page (cursor pagination only)
+ items:
+ $ref: '#/components/schemas/AuthSession'
+ has_more:
+ type: boolean
+ description: Whether a further page exists (cursor pagination only)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
+ '400':
+ description: Invalid or conflicting pagination parameters
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: User not found
+ delete:
+ tags:
+ - Auth Admin
+ summary: Delete all user sessions
+ description: |
+ Revokes all sessions for a user, forcing them to re-authenticate on all devices.
+ Use this to log out a user from everywhere.
+ operationId: deleteAllUserSessions
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: userId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: All sessions deleted
+ '404':
+ description: User not found
+ /projects/{id}/auth/users/{userId}/sessions/{sessionId}:
+ delete:
+ tags:
+ - Auth Admin
+ summary: Delete specific session
+ description: |
+ Revokes a specific session for a user.
+ Use this to log out a user from a single device.
+ operationId: deleteUserSession
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: userId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ - name: sessionId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Session deleted
+ '404':
+ description: Session or user not found
+ /projects/{id}/auth/users/{userId}/ban:
+ post:
+ tags:
+ - Auth Admin
+ summary: Ban a user
+ description: |
+ Bans a user temporarily or permanently. Banned users cannot sign in
+ and all their active sessions are immediately revoked.
+
+ - Omit `banned_until` for a permanent ban
+ - Provide `banned_until` ISO timestamp for a temporary ban
+ operationId: banAuthUser
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: userId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ banned_until:
+ type: string
+ format: date-time
+ description: When the ban expires (omit for permanent ban)
+ example: '2026-12-31T23:59:59Z'
+ responses:
+ '200':
+ description: User banned successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BanUserResponse'
+ '404':
+ description: User not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/auth/users/{userId}/unban:
+ post:
+ tags:
+ - Auth Admin
+ summary: Unban a user
+ description: |
+ Removes a ban from a user, restoring their ability to sign in.
+ The user's status is set back to 'active'.
+ operationId: unbanAuthUser
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: userId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: User unbanned successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UnbanUserResponse'
+ '404':
+ description: User not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/email-templates:
+ get:
+ tags:
+ - Auth Configuration
+ summary: List email templates
+ description: Returns all custom email templates for this project.
+ operationId: listEmailTemplates
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Email templates list
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/EmailTemplate'
+ post:
+ tags:
+ - Auth Configuration
+ summary: Create email template
+ description: |
+ Creates a custom email template for the project. Custom email templates
+ are a PRO-plan feature: requests from a FREE-plan project owner are
+ rejected with 403, and FREE projects always send the built-in default
+ templates regardless of any previously saved custom rows.
+ Every project is created with one template per type, so customizing one
+ is usually a PUT; creating a type the project already has returns 409.
+ Valid template types: welcome, confirmation, password_reset, password_changed
+ operationId: createEmailTemplate
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateEmailTemplateRequest'
+ responses:
+ '201':
+ description: Template created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmailTemplate'
+ '400':
+ description: Invalid template type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: Custom email templates require the PRO plan
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: The project already has a template of this type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/email-templates/{type}:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Get email template
+ operationId: getEmailTemplate
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: type
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - welcome
+ - confirmation
+ - password_reset
+ - password_changed
+ responses:
+ '200':
+ description: Email template
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmailTemplate'
+ '404':
+ description: Template not found
+ put:
+ tags:
+ - Auth Configuration
+ summary: Update email template
+ description: |
+ Updates a custom email template. Custom email templates are a PRO-plan
+ feature: requests from a FREE-plan project owner are rejected with 403
+ (including after a PRO→FREE downgrade), so a FREE project cannot modify
+ templates and always sends the built-in defaults.
+ operationId: updateEmailTemplate
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: type
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - welcome
+ - confirmation
+ - password_reset
+ - password_changed
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateEmailTemplateRequest'
+ responses:
+ '200':
+ description: Template updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmailTemplate'
+ '403':
+ description: Custom email templates require the PRO plan
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Template not found
+ delete:
+ tags:
+ - Auth Configuration
+ summary: Delete email template
+ description: |
+ Deletes a custom template, reverting to the default. Custom email
+ templates are a PRO-plan feature: requests from a FREE-plan project owner
+ are rejected with 403.
+ operationId: deleteEmailTemplate
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: type
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - welcome
+ - confirmation
+ - password_reset
+ - password_changed
+ responses:
+ '204':
+ description: Template deleted
+ '403':
+ description: Custom email templates require the PRO plan
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Template not found
+ /email-templates/defaults:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Get default email templates
+ description: Returns the default email templates used when no custom template is configured.
+ operationId: getDefaultEmailTemplates
+ responses:
+ '200':
+ description: Default templates
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/EmailTemplate'
+ /email-templates/defaults/{type}:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Get default email template by type
+ operationId: getDefaultEmailTemplate
+ parameters:
+ - name: type
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - welcome
+ - confirmation
+ - password_reset
+ - password_changed
+ responses:
+ '200':
+ description: Default template
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmailTemplate'
+ '404':
+ description: Template type not found
+ /projects/{id}/auth/config:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Get auth configuration
+ operationId: getAuthConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Auth configuration
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthConfig'
+ put:
+ tags:
+ - Auth Configuration
+ summary: Update auth configuration
+ description: |
+ Updates the project's auth configuration. Only the fields present in
+ the body are changed.
+ operationId: updateAuthConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateAuthConfigRequest'
+ responses:
+ '200':
+ description: Configuration updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthConfig'
+ '403':
+ description: |
+ The update would turn on, widen, or otherwise edit the email domain
+ allowlist (`allowed_email_domains`, `allowed_email_domains_mode`)
+ for a project that is not on the PRO plan. A FREE project keeps
+ whatever allowlist it already has — parked, enforcing nothing until
+ it upgrades — and may still remove it, so a downgrade never leaves a
+ project locked out of its own signups.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/auth/config/test-email:
+ post:
+ tags:
+ - Auth Configuration
+ summary: Send a test email using the project's saved SMTP config
+ description: |
+ Sends a diagnostic email to `to_email` using the project's
+ persisted `auth_config` SMTP credentials. If `html_body` or
+ `text_body` is supplied, the override path is taken: those
+ values (plus optional `subject`) are rendered through
+ html/text templates against the project's `Data` and
+ used as the body — used by the template editor's "Send Test"
+ affordance to preview an unsaved template. With both bodies
+ omitted, a hardcoded diagnostic message is sent and any
+ `subject` field is ignored. Sending `subject` alone (no
+ bodies) is rejected with 400 to avoid a silently-dropped
+ subject or a blank message. Also rejects with 400 if
+ `email_enabled=false` or `smtp_host` is empty.
+ operationId: testEmailConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TestEmailRequest'
+ responses:
+ '200':
+ description: Test email sent
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TestEmailResponse'
+ '400':
+ description: Invalid request or email delivery not configured
+ '401':
+ description: Unauthorized
+ '403':
+ description: Forbidden
+ '404':
+ description: Project not found
+ '502':
+ description: Template render failure or SMTP delivery failed
+ /projects/{id}/auth/hosted-pages/{pageType}:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Get hosted auth page
+ description: |
+ Returns the saved HTML/CSS for the page type, or `page: null` when the
+ project has not customized it yet. Always returns `defaults` (the theme
+ shell to seed an editor with, which is valid input to the update endpoint)
+ and `runtime` (the script the rendered page runs, plus a preview harness).
+ operationId: getAuthHostedPage
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: pageType
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/HostedAuthPageType'
+ responses:
+ '200':
+ description: Hosted page loaded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthHostedPageResponse'
+ put:
+ tags:
+ - Auth Configuration
+ summary: Update hosted auth page
+ description: |
+ Saves the current HTML/CSS for this page type.
+ Security validation rejects script tags, javascript: URLs, inline event handlers, iframe/object/embed/meta/link tags in HTML,
+ and closing style/head tags in CSS.
+ operationId: updateAuthHostedPage
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: pageType
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/HostedAuthPageType'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateAuthHostedPageRequest'
+ responses:
+ '200':
+ description: Hosted page updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthHostedPageResponse'
+ '400':
+ description: Invalid input or unsafe markup
+ '401':
+ description: Unauthorized
+ '403':
+ description: Forbidden
+ '404':
+ description: Project not found
+ /projects/{id}/auth/hosted/{pageType}:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Render managed reset-password page
+ description: |
+ Public HTML endpoint for the managed reset-password page.
+ Requires `Accept: text/html`.
+ Returns 404 when managed hosted pages are disabled for the project.
+ security: []
+ operationId: renderManagedAuthPage
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: pageType
+ in: path
+ required: true
+ schema:
+ $ref: '#/components/schemas/HostedRenderablePageType'
+ responses:
+ '200':
+ description: Hosted auth page HTML
+ content:
+ text/html:
+ schema:
+ type: string
+ '400':
+ description: Invalid project id or unsupported Accept header
+ '404':
+ description: Managed pages disabled or page type not found
+ /projects/{id}/auth/hosted:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Render default managed auth page
+ description: |
+ Public HTML endpoint for the managed login page.
+ Requires `Accept: text/html`.
+ security: []
+ operationId: renderDefaultManagedAuthPage
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: action
+ in: query
+ required: false
+ schema:
+ type: string
+ enum:
+ - login
+ - signup
+ - forgot-password
+ - device
+ description: |
+ Optional deep-link action for the unified hosted page. Ignored when a
+ custom login page is configured. `action=device` renders the device
+ authorization approval UI inline (no redirect to any external app);
+ it signs the user in and calls `POST /auth/device/verify`.
+ - name: user_code
+ in: query
+ required: false
+ schema:
+ type: string
+ description: Device user code (from `POST /auth/device/authorize`) used with `action=device`.
+ - name: anon_key
+ in: query
+ required: false
+ schema:
+ type: string
+ description: Project anon key used by built-in managed auth flows (required for login/signup/device actions).
+ - name: state
+ in: query
+ required: false
+ schema:
+ type: string
+ description: |
+ Opaque one-time nonce generated by the client SDK before redirecting
+ here. On successful login/signup it is echoed back in the post-auth
+ redirect fragment as `state`, so the SDK can bind the returned session
+ to the flow it initiated (login-CSRF / session-fixation defense). The
+ SDK rejects a returned session whose `state` does not match.
+ responses:
+ '200':
+ description: Hosted auth page HTML
+ content:
+ text/html:
+ schema:
+ type: string
+ '400':
+ description: Invalid project id or unsupported Accept header
+ '404':
+ description: Managed pages disabled
+ /projects/{id}/auth/hosted/login/options:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Get hosted login runtime options
+ description: |
+ Returns runtime options for the built-in managed login flow.
+ Requires `anon_key` query parameter.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+ security: []
+ operationId: getHostedLoginOptions
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: anon_key
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Hosted login options returned
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HostedLoginOptionsResponse'
+ '401':
+ description: Invalid or missing anon key
+ '404':
+ description: Managed pages disabled
+ '429':
+ description: Rate limit exceeded
+ /projects/{id}/auth/hosted/login/check-email:
+ post:
+ tags:
+ - Auth Configuration
+ summary: Check whether email exists for hosted login flow
+ description: |
+ Used by the built-in managed login page to branch UI between signin and signup.
+ Requires anon key in Authorization header.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+ security: []
+ operationId: hostedLoginCheckEmail
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: Authorization
+ in: header
+ required: true
+ schema:
+ type: string
+ description: Bearer anon key (`Bearer `)
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HostedLoginEmailCheckRequest'
+ responses:
+ '200':
+ description: Email existence evaluated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HostedLoginEmailCheckResponse'
+ '401':
+ description: Invalid or missing anon key
+ '429':
+ description: Rate limit exceeded
+ /projects/{id}/auth/methods:
+ get:
+ tags:
+ - Auth Configuration
+ summary: Get all authentication methods
+ description: |
+ Returns all configured authentication methods for this project,
+ including email/password, anonymous, device authorization, and OAuth providers.
+ operationId: getAuthMethods
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Authentication methods configuration
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ email_password:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ method:
+ type: string
+ name:
+ type: string
+ anonymous:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ method:
+ type: string
+ name:
+ type: string
+ oauth_providers:
+ type: array
+ items:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ method:
+ type: string
+ provider:
+ type: string
+ name:
+ type: string
+ redirect_url:
+ type: string
+ scopes:
+ type: array
+ items:
+ type: string
+ available_methods:
+ type: array
+ items:
+ type: string
+ example:
+ - email_password
+ - oauth_google
+ - oauth_github
+ put:
+ tags:
+ - Auth Configuration
+ summary: Configure authentication methods (unified)
+ description: |
+ Configure all authentication methods in a single request.
+ At least one method must remain enabled.
+ operationId: configureAuthMethods
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ enable_email_password:
+ type: boolean
+ enable_anonymous:
+ type: boolean
+ oauth_providers:
+ type: array
+ items:
+ type: object
+ properties:
+ provider:
+ type: string
+ enabled:
+ type: boolean
+ responses:
+ '200':
+ description: Methods configured
+ '400':
+ description: At least one method must be enabled
+ /projects/{id}/oauth/configs:
+ get:
+ tags:
+ - OAuth Configuration
+ summary: List OAuth configurations
+ description: List all OAuth provider configurations for this project
+ operationId: listOAuthConfigs
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: List of OAuth configurations
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ configs:
+ type: array
+ items:
+ $ref: '#/components/schemas/OAuthConfig'
+ post:
+ tags:
+ - OAuth Configuration
+ summary: Create OAuth configuration
+ description: Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device)
+ operationId: createOAuthConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateOAuthConfigRequest'
+ responses:
+ '201':
+ description: OAuth config created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OAuthConfig'
+ '409':
+ description: Provider already configured
+ /projects/{id}/oauth/configs/{provider}:
+ get:
+ tags:
+ - OAuth Configuration
+ summary: Get OAuth configuration
+ operationId: getOAuthConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - device
+ - name: client_id
+ in: query
+ required: false
+ schema:
+ type: string
+ description: Required when `provider=device` to select a specific device client.
+ responses:
+ '200':
+ description: OAuth configuration
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OAuthConfig'
+ put:
+ tags:
+ - OAuth Configuration
+ summary: Update OAuth configuration
+ operationId: updateOAuthConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - device
+ - name: client_id
+ in: query
+ required: false
+ schema:
+ type: string
+ description: Required when `provider=device` to select a specific device client.
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateOAuthConfigRequest'
+ responses:
+ '200':
+ description: OAuth config updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OAuthConfig'
+ delete:
+ tags:
+ - OAuth Configuration
+ summary: Delete OAuth configuration
+ operationId: deleteOAuthConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - device
+ - name: client_id
+ in: query
+ required: false
+ schema:
+ type: string
+ description: Required when `provider=device` to select a specific device client.
+ responses:
+ '204':
+ description: OAuth config deleted
+ /projects/{id}/oauth/providers:
+ get:
+ tags:
+ - OAuth Configuration
+ summary: List available OAuth providers
+ description: Get list of supported OAuth providers and their default scopes
+ operationId: listAvailableOAuthProviders
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Available providers
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ providers:
+ type: array
+ items:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ default_scopes:
+ type: array
+ items:
+ type: string
+ /auth/oauth/{provider}/authorize:
+ get:
+ tags:
+ - OAuth Authentication
+ summary: Start OAuth authorization
+ description: |
+ Redirects user to OAuth provider for authorization.
+ Handles CSRF protection with state parameter.
+ Project is identified via the anon_key query parameter.
+ operationId: authOAuthAuthorize
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - name: anon_key
+ in: query
+ required: true
+ schema:
+ type: string
+ description: Project anon key (required - identifies the project)
+ - name: redirect_url
+ in: query
+ schema:
+ type: string
+ description: |
+ URL to redirect to after the OAuth flow (optional). Must exactly
+ match an entry in the project's `allowed_redirect_urls`, including
+ its query string, or be the project's own managed hosted-auth page
+ URL.
+ - name: client_state
+ in: query
+ schema:
+ type: string
+ maxLength: 255
+ description: |
+ Optional application nonce. It is stored with the server-generated
+ provider state and echoed to redirect_url as `state`.
+ - name: response_mode
+ in: query
+ schema:
+ type: string
+ enum:
+ - code
+ description: |
+ Set to `code` to receive a short-lived authorization code at
+ redirect_url, then use POST /auth/oauth/exchange to obtain the
+ session. `redirect_url` is required in this mode. When omitted, the
+ established session-fragment response is retained for compatibility
+ with existing clients.
+ responses:
+ '307':
+ description: Redirect to OAuth provider
+ '400':
+ description: |
+ OAuth provider is disabled for this project, or `redirect_url` is
+ not registered in `allowed_redirect_urls`
+ '404':
+ description: OAuth provider not configured
+ /auth/oauth/{provider}/callback:
+ get:
+ tags:
+ - OAuth Authentication
+ summary: OAuth callback handler
+ description: |
+ Handles OAuth provider callback with authorization code.
+ Exchanges code for tokens and creates/signs in user.
+ operationId: authOAuthCallback
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - name: code
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: state
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: error
+ in: query
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Existing user signed in (when redirect_url was omitted)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthTokenResponse'
+ '201':
+ description: New user created and signed in (when redirect_url was omitted)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthTokenResponse'
+ '303':
+ description: |
+ Redirect to the exact registered redirect_url. Flows that requested
+ response_mode=code receive a short-lived, single-use `code` and
+ optional application `state`; compatibility flows receive the
+ established session fragment.
+ '400':
+ description: |
+ Missing/invalid code or state, the state parameter expired, or the
+ flow's stored redirect_url is no longer registered in
+ allowed_redirect_urls (re-checked at callback time)
+ '403':
+ description: |
+ The provider's email domain is not in `allowed_email_domains`. Creating
+ an account is refused under `signup` and `signup_and_signin`; signing in
+ an already-linked account is refused under `signup_and_signin`.
+ '409':
+ description: Email already exists (requires linking)
+ /auth/oauth/exchange:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Exchange OAuth authorization code
+ description: |
+ Atomically consumes a short-lived callback code and returns the user's
+ session. The request must use the same project anon key and exact
+ redirect_url that initiated the flow.
+ operationId: authOAuthExchange
+ security:
+ - AnonKey: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - code
+ - redirect_url
+ properties:
+ code:
+ type: string
+ redirect_url:
+ type: string
+ format: uri
+ responses:
+ '200':
+ description: Authorization code consumed and session created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthTokenResponse'
+ '400':
+ description: Invalid, expired, consumed, or redirect-mismatched code
+ '401':
+ description: Missing or invalid project anon key
+ '403':
+ description: |
+ Email confirmation is now required, or the account's email domain is not
+ in `allowed_email_domains` while `allowed_email_domains_mode` is
+ `signup_and_signin`. Both are re-checked here because the code outlives
+ the callback that issued it.
+ '429':
+ description: Too many exchange attempts from this client
+ /auth/device/authorize:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Start RFC8628 device authorization
+ description: |
+ Starts OAuth 2.0 Device Authorization Grant (RFC 8628).
+ Returns `device_code` for the CLI and `user_code` for browser verification.
+
+ By default the returned `verification_uri` / `verification_uri_complete`
+ point at the project's managed device-approval page served by this API
+ (`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`),
+ which requires managed auth enabled and a default anon key for the
+ project.
+
+ Projects can override this by setting `device_verification_url` on the
+ auth config (`PATCH /auth/config`). When set, that URL is returned as-is
+ with the `user_code` appended (no `action=device` hint and no embedded
+ anon key — the page brings its own), so a CLI's `login` command surfaces
+ the project's own RFC 8628 approval page. With a custom URL, device login
+ does **not** require managed auth to be enabled; the custom page's origin
+ must be in the project's auth CORS allowlist to call
+ `POST /auth/device/verify`. Either way the verification page must
+ authenticate the end user and call `POST /auth/device/verify` with the
+ `user_code`. See the device-auth guide for both approaches.
+ operationId: authDeviceAuthorize
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - client_id
+ properties:
+ client_id:
+ type: string
+ description: Enabled `device` OAuth client ID for the target project
+ responses:
+ '200':
+ description: Device authorization started
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DeviceAuthorizationResponse'
+ '400':
+ description: Invalid request or unauthorized client
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OAuthErrorResponse'
+ /auth/device/token:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Poll device token endpoint
+ description: |
+ RFC8628 token polling endpoint.
+ Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and `expired_token`.
+ operationId: authDeviceToken
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - grant_type
+ - device_code
+ - client_id
+ properties:
+ grant_type:
+ type: string
+ enum:
+ - urn:ietf:params:oauth:grant-type:device_code
+ device_code:
+ type: string
+ client_id:
+ type: string
+ responses:
+ '200':
+ description: Device flow completed, auth-user session minted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthTokenResponse'
+ '400':
+ description: Polling state/error response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OAuthErrorResponse'
+ '403':
+ description: |
+ `access_denied` - the approving account's email domain is not in
+ `allowed_email_domains` while `allowed_email_domains_mode` is
+ `signup_and_signin`. Re-checked here because approval and redemption
+ are separate requests.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OAuthErrorResponse'
+ /auth/device/verify:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Approve or deny a device code
+ description: |
+ Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a `user_code`.
+
+ Called by the verification page after the end user signs in. The grant is
+ scoped to the project the auth-user token belongs to: approving a
+ `user_code` issued for a different project returns `403`. This endpoint
+ does not require managed auth to be enabled, so a custom verification page
+ (hosted anywhere) can drive approval — it just needs an authenticated
+ project auth-user access token and, for cross-origin browser calls, the
+ page origin allowed in the project's auth CORS settings.
+ operationId: authDeviceVerify
+ security:
+ - AuthUserAccessToken: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - user_code
+ properties:
+ user_code:
+ type: string
+ action:
+ type: string
+ enum:
+ - approve
+ - deny
+ default: approve
+ responses:
+ '200':
+ description: Verification action accepted
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ status:
+ type: string
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/platform/exchange:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Exchange auth-user device session for platform token
+ description: |
+ Exchanges a verified auth-user device-flow session into a platform token for CLI usage.
+ The target platform user is derived from authenticated auth-user mapping; client cannot select another user.
+ operationId: authPlatformExchange
+ security:
+ - AuthUserAccessToken: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - client_id
+ properties:
+ client_id:
+ type: string
+ responses:
+ '200':
+ description: Platform token minted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PlatformExchangeResponse'
+ '403':
+ description: |
+ Exchange not allowed for this session/client/project, or the
+ account's email domain is not in `allowed_email_domains` while
+ `allowed_email_domains_mode` is `signup_and_signin`. The domain is
+ re-checked here because the minted platform token outlives the
+ session it is exchanged from.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/oauth/providers:
+ get:
+ tags:
+ - OAuth Authentication
+ summary: List user's linked providers
+ description: Get list of OAuth providers linked to current user
+ operationId: authListOAuthProviders
+ security:
+ - AuthUserAccessToken: []
+ responses:
+ '200':
+ description: Linked providers
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ providers:
+ type: array
+ items:
+ type: object
+ properties:
+ provider:
+ type: string
+ linked_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/oauth/{provider}/link:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Link OAuth provider to current user
+ description: |
+ Generates authorization URL to link OAuth provider to existing account.
+ User must be authenticated.
+ operationId: authLinkOAuthProvider
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - name: redirect_url
+ in: query
+ schema:
+ type: string
+ description: |
+ URL to redirect to after linking completes (optional). Same
+ allowed_redirect_urls requirement as GET /auth/oauth/{provider}/authorize.
+ - name: client_state
+ in: query
+ schema:
+ type: string
+ maxLength: 255
+ description: |
+ Optional application nonce echoed to redirect_url as `state`.
+ - name: response_mode
+ in: query
+ schema:
+ type: string
+ enum:
+ - code
+ description: |
+ Set to `code` to receive a short-lived authorization code at
+ redirect_url. `redirect_url` is required in this mode. When
+ omitted, the established session-fragment response is retained for
+ compatibility with existing clients.
+ responses:
+ '200':
+ description: Authorization URL generated
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ authorization_url:
+ type: string
+ '400':
+ description: redirect_url is not registered in allowed_redirect_urls
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: OAuth provider not configured
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: Provider already linked
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/oauth/{provider}/unlink:
+ delete:
+ tags:
+ - OAuth Authentication
+ summary: Unlink OAuth provider
+ description: |
+ Remove OAuth provider from user's account.
+ Cannot unlink if it's the only authentication method.
+ operationId: authUnlinkOAuthProvider
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ responses:
+ '204':
+ description: Provider unlinked
+ '400':
+ description: Cannot unlink last authentication method
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Provider not linked
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/oauth/{provider}/refresh-token:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Refresh OAuth provider token
+ description: |
+ Refresh the access token for an OAuth provider using its refresh token.
+ Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos).
+ operationId: refreshOAuthProviderToken
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ responses:
+ '200':
+ description: Token refreshed successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ provider:
+ type: string
+ expires_in:
+ type: integer
+ '400':
+ description: No refresh token available or refresh failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Provider not linked
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/oauth/{provider}/token:
+ get:
+ tags:
+ - OAuth Authentication
+ summary: Get current provider access token
+ description: |
+ Get valid access token for OAuth provider.
+ Automatically refreshes if expired.
+ operationId: getOAuthProviderToken
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ responses:
+ '200':
+ description: Current access token
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ provider:
+ type: string
+ expires_in:
+ type: integer
+ '401':
+ description: Not authenticated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Provider not linked
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /auth/oauth/{provider}/call-api:
+ post:
+ tags:
+ - OAuth Authentication
+ summary: Call OAuth provider API
+ description: |
+ Make an authenticated request to an OAuth provider's API on behalf of the user.
+ The user's stored access token is automatically used and refreshed if needed.
+
+ The request is always sent to the provider's fixed API base URL joined with
+ the caller-supplied `endpoint`. `endpoint` must be a relative path beginning
+ with `/` (optionally with a query string); it cannot change the target host.
+ Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are
+ rejected with `400` so the request can never be redirected to another host.
+
+ Examples of `endpoint`:
+ - Google userinfo: `/oauth2/v1/userinfo`
+ - GitHub repositories: `/user/repos`
+ - Microsoft Graph profile: `/me`
+
+ The response is the raw JSON response from the provider's API.
+ operationId: callOAuthProviderAPI
+ security:
+ - AuthUserAccessToken: []
+ parameters:
+ - name: provider
+ in: path
+ required: true
+ schema:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - endpoint
+ properties:
+ endpoint:
+ type: string
+ description: |
+ Relative path on the provider's API, beginning with `/`. It is
+ joined with the provider's fixed base URL; it must not contain a
+ scheme, host, userinfo, or a leading `//`.
+ example: /user/repos
+ method:
+ type: string
+ enum:
+ - GET
+ - POST
+ default: GET
+ description: HTTP method to use
+ body:
+ type: object
+ additionalProperties: true
+ description: Request body for POST requests
+ responses:
+ '200':
+ description: Provider API response
+ content:
+ application/json:
+ schema:
+ type: object
+ additionalProperties: true
+ description: Raw response from the OAuth provider's API
+ '400':
+ description: |
+ Invalid request (for example: missing `endpoint`, an `endpoint` that is
+ not a relative path, or an unsupported HTTP method).
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Not authenticated or provider not linked
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '502':
+ description: Provider API error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/anon-keys:
+ get:
+ tags:
+ - Anon Keys
+ summary: List anon keys
+ description: |
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and is the default when neither `cursor` nor `search` is
+ supplied (first page, default `limit`). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+ operationId: listAnonKeys
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: List of anon keys
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/AnonKey'
+ total:
+ type: integer
+ description: Total number of items matching the query (so the UI can render numbered pages).
+ has_more:
+ type: boolean
+ description: Whether a next page exists.
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
+ post:
+ tags:
+ - Anon Keys
+ summary: Create anon key
+ operationId: createAnonKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ description: |
+ Key name for identification.
+ Can only contain letters, numbers, underscores, and hyphens.
+ pattern: ^[A-Za-z0-9_-]+$
+ minLength: 1
+ maxLength: 255
+ example: frontend-app
+ permissions:
+ type: array
+ items:
+ type: string
+ enum:
+ - auth.signup
+ - auth.signin
+ - auth.refresh
+ - auth.logout
+ - auth.password_reset
+ - auth.confirm_email
+ - auth.resend_confirmation
+ - storage.upload
+ - storage.download
+ - storage.list
+ - storage.delete
+ - realtime.connect
+ - realtime.subscribe
+ - realtime.publish
+ - functions.invoke
+ description: |
+ Optional list of permissions for this key.
+ If not provided, defaults to auth-only permissions: auth.signup, auth.signin, auth.refresh, auth.logout, auth.password_reset, auth.confirm_email, auth.resend_confirmation.
+ Storage, realtime, and functions permissions must be explicitly added if needed.
+ example:
+ - auth.signup
+ - auth.signin
+ - auth.refresh
+ - auth.logout
+ responses:
+ '201':
+ description: Anon key created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AnonKey'
+ /projects/{id}/anon-keys/{keyId}:
+ get:
+ tags:
+ - Anon Keys
+ summary: Get anon key
+ description: Get details of a specific anon key
+ operationId: getAnonKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: keyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Anon key details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AnonKey'
+ '404':
+ description: Key not found
+ delete:
+ tags:
+ - Anon Keys
+ summary: Revoke anon key
+ description: Revokes key - it will immediately stop working
+ operationId: revokeAnonKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: keyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Key revoked
+ '401':
+ description: Unauthorized
+ '403':
+ description: Forbidden
+ '404':
+ description: Key not found
+ '409':
+ description: Cannot delete the project's default anon key
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/anon-keys/{keyId}/regenerate:
+ post:
+ tags:
+ - Anon Keys
+ summary: Regenerate anon key
+ description: Generate new JWT value for existing key
+ operationId: regenerateAnonKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: keyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Key regenerated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AnonKey'
+ /projects/{id}/anon-keys/{keyId}/set-default:
+ post:
+ tags:
+ - Anon Keys
+ summary: Set default anon key
+ description: Promotes the given key to the project's configured default. At most one key per project can be default.
+ operationId: setDefaultAnonKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: keyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Key set as default
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AnonKey'
+ '401':
+ description: Unauthorized
+ '403':
+ description: Forbidden
+ '404':
+ description: Anon key not found
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/service-keys:
+ get:
+ tags:
+ - Service Keys
+ summary: List service keys (paginated)
+ description: |
+ List all service role keys for a project with pagination.
+
+ **WARNING:** Service keys bypass RLS - for backend/admin use only!
+ operationId: listServiceKeys
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Paginated list of service keys
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PaginatedServiceKeys'
+ post:
+ tags:
+ - Service Keys
+ summary: Create service key
+ description: |
+ Create a new service role key for admin operations.
+
+ **WARNING:** Service keys bypass all RLS policies!
+ Store securely and NEVER expose in frontend code.
+ operationId: createServiceKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ description: |
+ Descriptive name for the key (e.g., "admin-dashboard", "background-jobs").
+ Can only contain letters, numbers, underscores, and hyphens.
+ pattern: ^[A-Za-z0-9_-]+$
+ minLength: 1
+ maxLength: 255
+ example: admin-dashboard
+ permissions:
+ type: array
+ items:
+ type: string
+ description: |
+ Optional least-privilege scope for the key. When omitted, empty, or
+ containing only blank strings, the key is granted full access (["*"])
+ for backward compatibility. Provide an explicit list (e.g.
+ ["functions.invoke", "locks.manage"]) to restrict the key; "*"
+ grants everything. Scope enforcement applies to function invocation,
+ storage object operations, and project locks.
+ example:
+ - functions.invoke
+ - locks.manage
+ responses:
+ '201':
+ description: Service key created - save the key_value immediately!
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServiceKey'
+ '409':
+ description: Key with this name already exists
+ /projects/{id}/service-keys/{keyId}:
+ get:
+ tags:
+ - Service Keys
+ summary: Get service key
+ description: Get details of a specific service key
+ operationId: getServiceKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: keyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Service key details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServiceKey'
+ '404':
+ description: Key not found
+ delete:
+ tags:
+ - Service Keys
+ summary: Delete service key
+ description: |
+ Permanently delete a service key.
+ Any services using this key will immediately lose access.
+ operationId: deleteServiceKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: keyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Key deleted
+ /projects/{id}/service-keys/{keyId}/regenerate:
+ post:
+ tags:
+ - Service Keys
+ summary: Regenerate service key
+ description: |
+ Generate new JWT value for existing key.
+ The old key is immediately invalidated.
+ Update your backend services with the new key before regenerating in production.
+ operationId: regenerateServiceKey
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: keyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Key regenerated - save the new key_value immediately!
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServiceKey'
+ /projects/{id}/storage/buckets:
+ get:
+ tags:
+ - Storage Buckets
+ summary: List all storage buckets in a project
+ description: |
+ With no pagination params, returns the full bucket list as a bare array
+ (legacy). Supplying `cursor`, `ending_before`, `search`, or `limit`
+ switches to keyset (cursor) pagination and returns a paginated envelope
+ with `next_cursor`/`prev_cursor` and a filtered `total`.
+ operationId: listStorageBuckets
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: |
+ Either the full bucket list (bare array, legacy) or a paginated
+ envelope when cursor pagination is requested.
+ content:
+ application/json:
+ schema:
+ oneOf:
+ - type: array
+ items:
+ $ref: '#/components/schemas/StorageBucket'
+ - $ref: '#/components/schemas/PaginatedStorageBuckets'
+ post:
+ tags:
+ - Storage Buckets
+ summary: Create a new storage bucket
+ operationId: createStorageBucket
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateStorageBucketRequest'
+ responses:
+ '201':
+ description: Bucket created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageBucket'
+ '409':
+ description: Bucket already exists
+ /projects/{id}/storage/buckets/{bucketName}:
+ get:
+ tags:
+ - Storage Buckets
+ summary: Get storage bucket by name
+ operationId: getStorageBucket
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/BucketName'
+ responses:
+ '200':
+ description: Bucket details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageBucket'
+ '404':
+ description: Bucket not found
+ patch:
+ tags:
+ - Storage Buckets
+ summary: Update storage bucket settings
+ operationId: updateStorageBucket
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/BucketName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateStorageBucketRequest'
+ responses:
+ '200':
+ description: Bucket updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageBucket'
+ delete:
+ tags:
+ - Storage Buckets
+ summary: Delete storage bucket and all objects
+ operationId: deleteStorageBucket
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/BucketName'
+ responses:
+ '200':
+ description: Bucket deleted
+ /projects/{id}/storage/buckets/{bucketName}/policies:
+ get:
+ tags:
+ - Storage Policies
+ summary: List storage policies for a bucket
+ operationId: listStoragePolicies
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/BucketName'
+ responses:
+ '200':
+ description: List of policies
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/StoragePolicy'
+ post:
+ tags:
+ - Storage Policies
+ summary: Create a storage policy
+ operationId: createStoragePolicy
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/BucketName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateStoragePolicyRequest'
+ responses:
+ '201':
+ description: Policy created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StoragePolicy'
+ /projects/{id}/storage/buckets/{bucketName}/policies/{policyId}:
+ delete:
+ tags:
+ - Storage Policies
+ summary: Delete a storage policy
+ operationId: deleteStoragePolicy
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - $ref: '#/components/parameters/BucketName'
+ - name: policyId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: Policy deleted
+ /projects/{id}/storage/objects:
+ get:
+ tags:
+ - Storage Admin
+ summary: List all storage objects in a project
+ description: |
+ Returns a paginated list of all storage objects across all buckets in the project.
+ Supports filtering by owner and pagination.
+ operationId: listStorageObjectsAdmin
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ - name: owner_id
+ in: query
+ description: Filter by owner user ID
+ schema:
+ type: string
+ format: uuid
+ - name: page
+ in: query
+ description: Page number (1-based)
+ schema:
+ type: integer
+ default: 1
+ minimum: 1
+ - name: limit
+ in: query
+ description: Items per page
+ schema:
+ type: integer
+ default: 50
+ minimum: 1
+ maximum: 100
+ - $ref: '#/components/parameters/Cursor'
+ - $ref: '#/components/parameters/EndingBefore'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Search'
+ responses:
+ '200':
+ description: Paginated list of storage objects
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/StorageObjectWithBucket'
+ page:
+ type: integer
+ limit:
+ type: integer
+ total:
+ type: integer
+ has_more:
+ type: boolean
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
+ /projects/{id}/storage/stats:
+ get:
+ tags:
+ - Storage Admin
+ summary: Get storage statistics for a project
+ description: Returns aggregate storage statistics including bucket count, object count, and total size.
+ operationId: getStorageStats
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Storage statistics
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageStats'
+ /projects/{id}/realtime/config:
+ get:
+ tags:
+ - Realtime
+ summary: Get realtime configuration for a project
+ description: Returns the realtime configuration including enabled features and limits.
+ operationId: getRealtimeConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Realtime configuration
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RealtimeConfig'
+ '401':
+ description: Unauthorized
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '404':
+ description: Project not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ put:
+ tags:
+ - Realtime
+ summary: Update realtime configuration for a project
+ description: Updates realtime settings including feature toggles and limits.
+ operationId: updateRealtimeConfig
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateRealtimeConfigRequest'
+ responses:
+ '200':
+ description: Updated realtime configuration
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RealtimeConfig'
+ '400':
+ description: Invalid configuration values
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Unauthorized
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /projects/{id}/realtime/stats:
+ get:
+ tags:
+ - Realtime
+ summary: Get realtime statistics for a project
+ description: Returns realtime usage statistics including connection counts and subscribed tables.
+ operationId: getRealtimeStats
+ security:
+ - UserToken: []
+ parameters:
+ - $ref: '#/components/parameters/ProjectId'
+ responses:
+ '200':
+ description: Realtime statistics
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RealtimeStats'
+ '401':
+ description: Unauthorized
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /storage/{bucketName}:
+ get:
+ tags:
+ - Storage Objects
+ summary: List objects in a bucket
+ operationId: listStorageObjects
+ security:
+ - AnonKey: []
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ - name: prefix
+ in: query
+ description: Filter objects by path prefix
+ schema:
+ type: string
+ - name: limit
+ in: query
+ description: Maximum objects to return
+ schema:
+ type: integer
+ default: 50
+ maximum: 1000
+ - name: cursor
+ in: query
+ description: Pagination cursor
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of objects
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageListResponse'
+ '403':
+ description: Access denied by storage policy
+ '429':
+ $ref: '#/components/responses/BandwidthCapExceeded'
+ /locks/{key}/lease:
+ post:
+ tags:
+ - Locks
+ summary: Acquire a project lock
+ description: |
+ Acquires a project-scoped lease using the project embedded in the service-role key.
+ The caller must hold the `locks.manage` permission. Repeating the request with the
+ same lock token is idempotent and resets that lease to the requested TTL. A different
+ live owner receives `409 lock_held`; a caller whose own lease already lapsed receives
+ `409 lock_ownership_lost`.
+ operationId: acquireProjectLock
+ security:
+ - ServiceRoleKey: []
+ parameters:
+ - $ref: '#/components/parameters/LockKey'
+ - $ref: '#/components/parameters/LockToken'
+ - $ref: '#/components/parameters/LockRequestId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectLockLeaseRequest'
+ responses:
+ '201':
+ description: Lease acquired
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectLockLease'
+ '400':
+ description: Invalid lock key, token, or TTL
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Missing or invalid credentials
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: A non-service credential was supplied or the service key lacks `locks.manage`
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: |
+ The lock is held by another live lease (`lock_held`), or the caller's own lease
+ lapsed and is not yet reclaimable (`lock_ownership_lost`).
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Project lock request limit exceeded
+ headers:
+ Retry-After:
+ description: Seconds until the current fixed-minute window ends.
+ schema:
+ type: integer
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Lock service unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ patch:
+ tags:
+ - Locks
+ summary: Renew a project lock
+ description: |
+ Renews a lease owned by the supplied lock token. The request must arrive
+ more than one second before `expires_at`; this safety margin prevents
+ clock skew between regional API instances from resurrecting an expired
+ lease.
+ operationId: renewProjectLock
+ security:
+ - ServiceRoleKey: []
+ parameters:
+ - $ref: '#/components/parameters/LockKey'
+ - $ref: '#/components/parameters/LockToken'
+ - $ref: '#/components/parameters/LockRequestId'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectLockLeaseRequest'
+ responses:
+ '200':
+ description: Lease renewed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectLockLease'
+ '400':
+ description: Invalid lock key, token, or TTL
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Missing or invalid credentials
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: A non-service credential was supplied or the service key lacks `locks.manage`
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: The lease expired or is owned by another token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Project lock request limit exceeded
+ headers:
+ Retry-After:
+ description: Seconds until the current fixed-minute window ends.
+ schema:
+ type: integer
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Lock service unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Locks
+ summary: Release a project lock
+ description: Releases a lease only when the supplied lock token still owns it.
+ operationId: releaseProjectLock
+ security:
+ - ServiceRoleKey: []
+ parameters:
+ - $ref: '#/components/parameters/LockKey'
+ - $ref: '#/components/parameters/LockToken'
+ - $ref: '#/components/parameters/LockRequestId'
+ responses:
+ '204':
+ description: Lease released
+ '400':
+ description: Invalid lock key or token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Missing or invalid credentials
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: A non-service credential was supplied or the service key lacks `locks.manage`
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '409':
+ description: The lease is owned by another token
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Project lock request limit exceeded
+ headers:
+ Retry-After:
+ description: Seconds until the current fixed-minute window ends.
+ schema:
+ type: integer
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Lock service unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /locks/{key}:
+ get:
+ tags:
+ - Locks
+ summary: Read a project lock
+ description: |
+ Reports whether the lock is currently held, when its lease expires, and the
+ holder's fencing token. `held` follows takeover eligibility rather than raw
+ expiry, so `held: false` means an acquire would succeed now. No lock token is
+ required, making this usable for monitoring and recovery.
+ operationId: getProjectLock
+ security:
+ - ServiceRoleKey: []
+ parameters:
+ - $ref: '#/components/parameters/LockKey'
+ - $ref: '#/components/parameters/LockRequestId'
+ responses:
+ '200':
+ description: Current lock state
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectLockState'
+ '400':
+ description: Invalid lock key
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Missing or invalid credentials
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: A non-service credential was supplied or the service key lacks `locks.manage`
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Project lock request limit exceeded
+ headers:
+ Retry-After:
+ description: Seconds until the current fixed-minute window ends.
+ schema:
+ type: integer
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Lock service unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags:
+ - Locks
+ summary: Force release a project lock
+ description: |
+ Drops the lease whatever token holds it, for recovering a lock whose holder
+ died without releasing. Use `DELETE /locks/{key}/lease` for normal release.
+
+ This breaks mutual exclusion by itself: the previous holder keeps working
+ until its own renewal fails. Guard the protected resource with the lease's
+ `fencing_token`, which the next acquisition raises, so a write from the
+ displaced holder can be rejected. Succeeds when the lock is already absent.
+ operationId: forceReleaseProjectLock
+ security:
+ - ServiceRoleKey: []
+ parameters:
+ - $ref: '#/components/parameters/LockKey'
+ - $ref: '#/components/parameters/LockRequestId'
+ responses:
+ '204':
+ description: Lock released
+ '400':
+ description: Invalid lock key
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '401':
+ description: Missing or invalid credentials
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '403':
+ description: A non-service credential was supplied or the service key lacks `locks.manage`
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '429':
+ description: Project lock request limit exceeded
+ headers:
+ Retry-After:
+ description: Seconds until the current fixed-minute window ends.
+ schema:
+ type: integer
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ '503':
+ description: Lock service unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ /storage/{bucketName}/move:
+ post:
+ tags:
+ - Storage Objects
+ summary: Move/rename an object
+ operationId: moveStorageObject
+ security:
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageMoveRequest'
+ responses:
+ '200':
+ description: Object moved
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageObject'
+ '403':
+ description: Access denied by storage policy
+ '429':
+ $ref: '#/components/responses/BandwidthCapExceeded'
+ /storage/{bucketName}/copy:
+ post:
+ tags:
+ - Storage Objects
+ summary: Copy an object
+ operationId: copyStorageObject
+ security:
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageCopyRequest'
+ responses:
+ '201':
+ description: Object copied
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageObject'
+ '403':
+ description: Access denied by storage policy
+ '429':
+ $ref: '#/components/responses/BandwidthCapExceeded'
+ /storage/{bucketName}/{path}:
+ post:
+ tags:
+ - Storage Objects
+ summary: Upload a file or create resumable session
+ description: |
+ Unified endpoint for file uploads. Behavior depends on Content-Type and headers:
+
+ **Simple Upload (multipart/form-data):**
+ Upload a complete file in a single request. Best for files under 100MB.
+
+ **Create Resumable Session (application/json):**
+ Create a session for chunked uploads. Best for large files or unreliable networks.
+ Requires: `Content-Type: application/json` with body `{"filename": "...", "content_type": "...", "total_size": ...}`
+
+ **Complete Resumable Session:**
+ Complete a session after all parts are uploaded.
+ Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header.
+ operationId: uploadStorageObject
+ security:
+ - AnonKey: []
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ - name: path
+ in: path
+ required: true
+ description: Object path within bucket
+ schema:
+ type: string
+ - name: X-Upload-Session
+ in: header
+ required: false
+ description: Upload session ID (for completing resumable uploads)
+ schema:
+ type: string
+ - name: X-Upload-Complete
+ in: header
+ required: false
+ description: Set to "true" to complete a resumable upload session
+ schema:
+ type: string
+ enum:
+ - 'true'
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ required:
+ - file
+ properties:
+ file:
+ type: string
+ format: binary
+ description: File to upload (simple upload)
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateUploadSessionRequest'
+ responses:
+ '200':
+ description: Resumable upload completed (when X-Upload-Complete=true)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CompleteUploadSessionResponse'
+ '201':
+ description: File uploaded or session created
+ content:
+ application/json:
+ schema:
+ oneOf:
+ - $ref: '#/components/schemas/StorageObject'
+ - $ref: '#/components/schemas/CreateUploadSessionResponse'
+ '400':
+ description: |
+ Bad request. This can occur when:
+ - MIME type is not in the bucket's allowed_mime_types list
+ - File exceeds the bucket's configured file_size_limit
+ - File exceeds the global maximum upload size (5GB)
+ - Invalid request body or missing required fields
+ '403':
+ description: Access denied by storage policy
+ '413':
+ description: |
+ File size exceeds plan-based limits. This occurs when:
+ - File exceeds the plan-based maximum file size (FREE or PRO tier)
+ - Upload would exceed the project's total storage quota
+ '429':
+ $ref: '#/components/responses/BandwidthCapExceeded'
+ put:
+ tags:
+ - Storage Objects
+ summary: Upload a part of a resumable upload
+ description: |
+ Upload a single part of a resumable upload session.
+
+ **Requirements:**
+ - Part numbers start at 1
+ - All parts except the last must be at least 5MB
+ - Maximum part size is 25MB
+ - Parts can be uploaded in any order
+ - Re-uploading a part overwrites the previous upload
+ operationId: uploadPart
+ security:
+ - AnonKey: []
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ - name: path
+ in: path
+ required: true
+ description: Object path within bucket
+ schema:
+ type: string
+ - name: X-Upload-Session
+ in: header
+ required: true
+ description: Upload session ID
+ schema:
+ type: string
+ - name: X-Part-Number
+ in: header
+ required: true
+ description: Part number (1 to 10000)
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 10000
+ requestBody:
+ required: true
+ content:
+ application/octet-stream:
+ schema:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: Part uploaded
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UploadSessionPart'
+ '400':
+ description: Invalid part number or part data
+ '403':
+ description: Access denied
+ '404':
+ description: Session not found
+ get:
+ tags:
+ - Storage Objects
+ summary: Download a file or get upload session status
+ description: |
+ Download a file, or get the status of a resumable upload session.
+
+ **File Download (default):**
+ Downloads the file at the specified path.
+
+ **Session Status (with X-Upload-Session header):**
+ Returns the status of a resumable upload session, including which parts have been uploaded.
+ operationId: downloadStorageObject
+ security:
+ - AnonKey: []
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ - name: path
+ in: path
+ required: true
+ description: Object path within bucket
+ schema:
+ type: string
+ - name: Range
+ in: header
+ required: false
+ description: |
+ HTTP Range header for partial downloads.
+ Format: bytes=start-end or bytes=start-
+ Examples: bytes=0-1023, bytes=1000-
+ schema:
+ type: string
+ pattern: ^bytes=\d+-\d*$
+ - name: X-Upload-Session
+ in: header
+ required: false
+ description: Upload session ID (to get session status instead of downloading)
+ schema:
+ type: string
+ responses:
+ '200':
+ description: File content or session status
+ headers:
+ Content-Type:
+ schema:
+ type: string
+ Content-Length:
+ schema:
+ type: integer
+ ETag:
+ schema:
+ type: string
+ content:
+ application/octet-stream:
+ schema:
+ type: string
+ format: binary
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UploadSessionStatusResponse'
+ '206':
+ description: Partial content (range request)
+ '400':
+ description: Invalid Range header format
+ '403':
+ description: Access denied by storage policy
+ '404':
+ description: Object or session not found
+ '429':
+ $ref: '#/components/responses/BandwidthCapExceeded'
+ delete:
+ tags:
+ - Storage Objects
+ summary: Delete a file or abort upload session
+ description: |
+ Delete a file, or abort a resumable upload session.
+
+ **File Delete (default):**
+ Deletes the file at the specified path.
+
+ **Abort Session (with X-Upload-Session header):**
+ Aborts a resumable upload session and cleans up any uploaded parts.
+ operationId: deleteStorageObject
+ security:
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ - name: path
+ in: path
+ required: true
+ description: Object path within bucket
+ schema:
+ type: string
+ - name: X-Upload-Session
+ in: header
+ required: false
+ description: Upload session ID (to abort session instead of deleting file)
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Object deleted or session aborted
+ '403':
+ description: Access denied by storage policy
+ '404':
+ description: Object or session not found
+ '429':
+ $ref: '#/components/responses/BandwidthCapExceeded'
+ /storage/{bucketName}/{path}/visibility:
+ patch:
+ tags:
+ - Storage Objects
+ summary: Update file visibility (public/private)
+ description: |
+ Change whether a file is publicly accessible. Only the file owner or a service key can change visibility.
+ If the bucket defines UPDATE policies, the owner must also satisfy one of them.
+
+ - Public files can be downloaded with just an anon key (no user authentication required)
+ - Private files (default) require authentication and must pass policy checks
+ - All downloads go through the Volcano API - there is no direct access to the underlying store
+ operationId: updateStorageObjectVisibility
+ security:
+ - ServiceRoleKey: []
+ - AuthUserAccessToken: []
+ parameters:
+ - $ref: '#/components/parameters/BucketName'
+ - name: path
+ in: path
+ required: true
+ description: Object path within bucket
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageVisibilityRequest'
+ responses:
+ '200':
+ description: Visibility updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StorageObject'
+ '403':
+ description: Not the file owner or denied by the bucket's UPDATE policies
+ '404':
+ description: Object not found
+ /public/{projectId}/{bucketName}/{path}:
+ get:
+ tags:
+ - Storage Objects
+ summary: Download a public file (no authentication required)
+ description: |
+ Download a file that has been marked as public. This endpoint requires NO authentication.
+
+ **Access Requirements:**
+ - The file must have `is_public: true` set via the visibility endpoint
+ - Private files will return 403 Forbidden
+
+ **Use Cases:**
+ - Shareable public URLs for profile pictures, public documents, etc.
+ - Embedding public files on external websites
+ - Direct linking without requiring SDK or authentication
+
+ **URL Format:**
+ ```
+ GET /public/{projectId}/{bucketName}/{path}
+ ```
+
+ **Example:**
+ ```
+ https://api.volcano.dev/public/abc123/avatars/user-photo.jpg
+ ```
+
+ **CORS:**
+ This endpoint allows all origins since the file is already public.
+ operationId: downloadPublicFile
+ parameters:
+ - name: projectId
+ in: path
+ required: true
+ description: Project ID
+ schema:
+ type: string
+ format: uuid
+ - $ref: '#/components/parameters/BucketName'
+ - name: path
+ in: path
+ required: true
+ description: Object path within bucket
+ schema:
+ type: string
+ responses:
+ '200':
+ description: File content
+ content:
+ '*/*':
+ schema:
+ type: string
+ format: binary
+ '206':
+ description: Partial content (range request)
+ '404':
+ description: Not found (file doesn't exist or is not public)
+ '429':
+ $ref: '#/components/responses/BandwidthCapExceeded'
+ /health:
+ get:
+ tags:
+ - System
+ summary: Health check endpoint
+ description: Returns server health status. Used for load balancer and monitoring checks.
+ operationId: healthCheck
+ responses:
+ '200':
+ description: Server is healthy
+ content:
+ text/plain:
+ schema:
+ type: string
+ example: OK
+components:
+ securitySchemes:
+ AnonKey:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+ description: |
+ Project-specific public key for frontend authentication.
+ Required for signup, signin, refresh, and logout endpoints.
+ Get from Project Settings → Authentication → Anon Keys.
+ Safe to expose in frontend code (scoped to project, limited permissions).
+ AuthUserAccessToken:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+ description: |
+ Auth user access token obtained from signup/signin.
+ Used for authenticated function invocation and user profile access.
+ Functions invoked with access tokens receive user context in event.__volcano_auth.
+ Expires after configured lifetime (default: 1 hour).
+ ServiceRoleKey:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+ description: |
+ Service role key for admin operations.
+ **WARNING:** Bypasses Row-Level Security - backend use only!
+ Create via POST /projects/{id}/service-keys.
+ Used for function invocation with full database access.
+ UserToken:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+ description: |
+ Platform user token from the Management API.
+ Required for project management operations.
+ Obtain via POST /tokens in Management API (port 8001).
+ parameters:
+ BranchName:
+ name: branchName
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: ^[a-z0-9_]+$
+ maxLength: 64
+ description: Branch name (unique within the parent database, lowercase letters, numbers, and underscores only)
+ BucketName:
+ name: bucketName
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: ^[a-zA-Z0-9_-]+$
+ minLength: 1
+ maxLength: 64
+ description: Storage bucket name
+ Cursor:
+ name: cursor
+ in: query
+ required: false
+ schema:
+ type: string
+ description: |
+ Opaque keyset pagination cursor from a previous response's `next_cursor`
+ — pages forward. Mutually exclusive with `page` and `ending_before`;
+ combining them returns 400. When supplied, the request's `search` and
+ `limit` must match the values bound to the cursor or the request returns 400.
+ EndingBefore:
+ name: ending_before
+ in: query
+ required: false
+ schema:
+ type: string
+ description: |
+ Opaque keyset pagination cursor from a previous response's `prev_cursor`
+ — pages backward (the page immediately preceding this cursor). Mutually
+ exclusive with `page` and `cursor`; combining them returns 400. `search`
+ and `limit` must match the values bound to the cursor or the request
+ returns 400.
+ DatabaseName:
+ name: databaseName
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: ^[a-z0-9_]+$
+ maxLength: 64
+ description: Database name (unique within project, lowercase letters, numbers, and underscores only)
+ DeploymentId:
+ name: deploymentId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ description: Frontend deployment ID
+ FrontendId:
+ name: frontendId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ description: Frontend ID
+ FunctionId:
+ name: functionId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ description: Function ID
+ Limit:
+ name: limit
+ in: query
+ required: false
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 10
+ description: Number of items per page (max 100)
+ LockKey:
+ name: key
+ in: path
+ required: true
+ description: Project-local lock name.
+ schema:
+ type: string
+ minLength: 1
+ maxLength: 128
+ pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
+ LockToken:
+ name: X-Volcano-Lock-Token
+ in: header
+ required: true
+ description: Opaque UUID generated once by the caller and retained for the lease lifetime.
+ schema:
+ type: string
+ format: uuid
+ LockRequestId:
+ name: X-Volcano-Request-Id
+ in: header
+ required: true
+ description: |
+ UUID correlating this request across client and server logs. Repeat safety comes from
+ the lock token, so a retry under a reused request ID still counts against the quota.
+ schema:
+ type: string
+ format: uuid
+ DeploymentOperation:
+ name: operation
+ in: query
+ required: false
+ description: Restrict a deployment feed to one kind of operation.
+ schema:
+ type: string
+ enum:
+ - deploy
+ - redeploy
+ - update
+ - delete
+ DeploymentOwnerId:
+ name: owner_id
+ in: query
+ required: false
+ description: |
+ The user who owns the projects whose deployments to return
+ (`projects.user_id`). This is ownership, not the actor that started the
+ deployment — see `initiated_by_user_id` for that. Not a UUID: platform
+ user ids are opaque strings.
+ schema:
+ type: string
+ maxLength: 255
+ DeploymentOrder:
+ name: order
+ in: query
+ required: false
+ description: |
+ Sort key and direction. `created_at.desc` (default) is the feed order.
+ `completed_at.asc` orders finished attempts by completion, oldest first,
+ and excludes attempts that never completed.
+ schema:
+ type: string
+ enum:
+ - created_at.desc
+ - completed_at.asc
+ default: created_at.desc
+ DeploymentResourceType:
+ name: resource_type
+ in: query
+ required: false
+ description: |
+ Restrict a deployment feed to a single resource type. Omit to return
+ both Function and Frontend deployments.
+ schema:
+ type: string
+ enum:
+ - function
+ - frontend
+ DeploymentStatus:
+ name: status
+ in: query
+ required: false
+ description: Restrict a deployment feed to attempts in one status.
+ schema:
+ type: string
+ enum:
+ - queued
+ - provisioning
+ - active
+ - degraded
+ - failed
+ - superseded
+ - deleting
+ - deleted
+ Offset:
+ name: offset
+ in: query
+ required: false
+ schema:
+ type: integer
+ minimum: 0
+ default: 0
+ description: |
+ Bounded row offset past the keyset anchor named by `cursor` (forward) or
+ `ending_before` (backward) — the hybrid jump. Seek to the anchor, then
+ skip this many rows within. Used for numbered jump-to-page: from the
+ current page, seek to its next/prev cursor and offset the remaining
+ pages. Only honored on the cursor pagination path; ignored otherwise.
+ Page:
+ name: page
+ in: query
+ required: false
+ schema:
+ type: integer
+ minimum: 1
+ description: |
+ Page number (1-indexed) for offset pagination. Declares no schema
+ default so the request validator does not inject one: handlers that omit
+ `page` see it unset (nil) and default to 1 in code, while cursor-first
+ endpoints (e.g. the project deployments feed) can detect its absence to
+ stay in keyset/search mode. Supplying `page` selects offset pagination.
+ ProjectId:
+ name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ description: Project ID
+ Search:
+ name: search
+ in: query
+ required: false
+ schema:
+ type: string
+ maxLength: 256
+ description: |
+ Case-insensitive substring match on the resource `name`. See the
+ endpoint description for supported pagination modes.
+ SchedulerId:
+ name: schedulerId
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ description: Function scheduler ID
+ VariableName:
+ name: name
+ in: path
+ required: true
+ schema:
+ type: string
+ minLength: 1
+ maxLength: 256
+ pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
+ description: Variable name
+ responses:
+ BandwidthCapExceeded:
+ description: |
+ The platform user exceeded their billing-cycle bandwidth allowance (aggregate
+ ingress + egress across owned projects). Enforcement is eventual:
+ requests are rejected until the allowance increases or the next
+ anniversary cycle begins.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ DatabaseQueryCapExceeded:
+ description: |
+ The query was rejected by a billing-cycle allowance: either the owning
+ platform user's bandwidth allowance (aggregate ingress + egress across
+ owned projects) or their database-request allowance. Enforcement is
+ eventual: queries are rejected until the allowance increases or the
+ next anniversary cycle begins. The error message identifies the resource.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ schemas:
+ AnonKey:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ key_value:
+ type: string
+ description: JWT token - use this in frontend Authorization header
+ permissions:
+ type: array
+ items:
+ type: string
+ description: |
+ Permissions granted to this anon key.
+ Auth permissions: auth.signup, auth.signin, auth.refresh, auth.logout, auth.password_reset, auth.confirm_email, auth.resend_confirmation
+ Storage permissions: storage.upload, storage.download, storage.list, storage.delete
+ Realtime permissions: realtime.connect, realtime.subscribe, realtime.publish
+ Functions permissions: functions.invoke
+ example:
+ - auth.signup
+ - auth.signin
+ - auth.refresh
+ - auth.logout
+ is_default:
+ type: boolean
+ description: Whether this is the project's configured default anon key. Only one key per project can be default.
+ created_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - name
+ - key_value
+ AuthConfig:
+ type: object
+ properties:
+ project_id:
+ type: string
+ format: uuid
+ access_token_lifetime:
+ type: integer
+ description: Access token lifetime in seconds
+ default: 3600
+ refresh_token_lifetime:
+ type: integer
+ description: Refresh token lifetime in seconds
+ default: 2592000
+ inactivity_timeout:
+ type: integer
+ description: Force re-login after inactivity (seconds, 0=never)
+ default: 0
+ max_session_duration:
+ type: integer
+ description: Force re-login after duration (seconds, 0=never)
+ default: 0
+ min_password_length:
+ type: integer
+ minimum: 15
+ maximum: 128
+ default: 15
+ description: Configured minimum password length in Unicode characters.
+ password_policy:
+ $ref: '#/components/schemas/AuthPasswordPolicy'
+ require_uppercase:
+ type: boolean
+ default: false
+ require_lowercase:
+ type: boolean
+ default: false
+ require_numbers:
+ type: boolean
+ default: false
+ require_special_chars:
+ type: boolean
+ default: false
+ enable_signup:
+ type: boolean
+ description: Master switch - allow new user signups via ANY provider
+ default: true
+ enable_email_password:
+ type: boolean
+ description: Enable email/password authentication as a provider
+ default: true
+ rate_limit_signup:
+ type: integer
+ description: Signups per hour per IP
+ default: 100
+ rate_limit_signin:
+ type: integer
+ description: Signins per hour per IP
+ default: 100
+ rate_limit_token_refresh:
+ type: integer
+ description: Refreshes per hour per IP
+ default: 1000
+ cors_enabled:
+ type: boolean
+ default: false
+ cors_allowed_origins:
+ type: array
+ items:
+ type: string
+ example:
+ - https://myapp.com
+ - http://localhost:3000
+ enable_anonymous_signins:
+ type: boolean
+ description: Allow creating users without email/password
+ default: false
+ allowed_email_domains:
+ type: array
+ description: |
+ Email domains allowed to create users in this project. Applies to
+ email/password signup, OAuth/SSO signup, anonymous conversion, and
+ email changes. Empty (the default) allows every domain.
+
+ Entries are stored normalized (lowercase, no `@` prefix) and match
+ the domain part exactly: `domain1.com` does not cover
+ `mail.domain1.com`. Signups from other domains are rejected with
+ 403, and `allowed_email_domains_mode` decides whether sign-in is
+ covered as well.
+
+ The allowlist is a PRO feature to configure and to enforce. A
+ downgrade parks it: the domains are still returned here and stop
+ being applied until the project is back on PRO.
+ items:
+ type: string
+ example:
+ - domain1.com
+ - domain2.com
+ allowed_email_domains_mode:
+ type: string
+ description: |
+ How far `allowed_email_domains` reaches. `signup` only gates account
+ creation, so accounts that predate the list keep signing in.
+ `signup_and_signin` also refuses to issue a session to an account
+ whose domain is not listed. `disabled` keeps the list without
+ enforcing it.
+ enum:
+ - disabled
+ - signup
+ - signup_and_signin
+ default: signup
+ platform_token_ttl:
+ type: integer
+ description: TTL in seconds for platform tokens minted via `/auth/platform/exchange`
+ default: 2592000
+ allow_password_reset:
+ type: boolean
+ description: Enable forgot password flow
+ default: true
+ password_reset_timeout:
+ type: integer
+ description: Recovery token expiry in seconds
+ default: 3600
+ max_password_history:
+ type: integer
+ description: Number of previous passwords to remember (0=disabled)
+ default: 0
+ cors_allow_credentials:
+ type: boolean
+ description: Allow credentials in CORS requests
+ default: true
+ cors_max_age:
+ type: integer
+ description: CORS preflight cache duration (seconds)
+ default: 86400
+ require_email_confirmation:
+ type: boolean
+ description: Require users to confirm email before sign-in. Can only be true when email_enabled is true.
+ default: false
+ email_confirmation_timeout:
+ type: integer
+ description: Email confirmation token expiry in seconds.
+ default: 86400
+ auto_link_verified_oauth:
+ type: boolean
+ description: Link a verified OAuth identity to an existing confirmed account with the same email instead of returning a conflict. Requires require_email_confirmation to be true.
+ default: false
+ email_enabled:
+ type: boolean
+ description: Enable transactional email sending (confirmation, reset, change notifications). Must be true when require_email_confirmation is true.
+ default: false
+ email_from_address:
+ type: string
+ email_from_name:
+ type: string
+ smtp_host:
+ type: string
+ smtp_port:
+ type: integer
+ default: 587
+ smtp_username:
+ type: string
+ smtp_password_configured:
+ type: boolean
+ description: Whether an SMTP password is configured. The password itself is never returned.
+ default: false
+ smtp_use_tls:
+ type: boolean
+ default: true
+ email_confirmation_subject:
+ type: string
+ email_password_reset_subject:
+ type: string
+ email_password_changed_subject:
+ type: string
+ managed_auth_enabled:
+ type: boolean
+ description: Enables project-hosted managed auth pages.
+ default: false
+ post_auth_redirect_url:
+ type: string
+ description: Default redirect target after successful hosted auth.
+ allowed_redirect_urls:
+ type: array
+ description: Redirect allowlist used to validate post_auth_redirect_url and post_logout_redirect_url.
+ items:
+ type: string
+ post_logout_redirect_url:
+ type: string
+ description: Redirect target after logout from hosted pages.
+ device_verification_url:
+ type: string
+ description: |
+ Optional override for the device-authorization verification page.
+ When set, POST /auth/device/authorize returns this URL (with the
+ user_code) as verification_uri/verification_uri_complete instead of
+ the built-in managed device page. Lets a CLI surface the project's
+ own RFC 8628 approval page. Empty falls back to the managed page.
+ example: https://app.acme.com/device
+ required:
+ - password_policy
+ AuthInsightsInterval:
+ type: string
+ enum:
+ - day
+ - week
+ - month
+ AuthInsightsResponse:
+ type: object
+ additionalProperties: false
+ properties:
+ project_id:
+ type: string
+ format: uuid
+ observed_at:
+ type: string
+ format: date-time
+ window:
+ $ref: '#/components/schemas/AuthInsightsWindow'
+ summary:
+ $ref: '#/components/schemas/AuthInsightsSummary'
+ series:
+ type: array
+ items:
+ $ref: '#/components/schemas/AuthInsightsSeriesPoint'
+ required:
+ - project_id
+ - observed_at
+ - window
+ - summary
+ - series
+ AuthInsightsSeriesPoint:
+ type: object
+ additionalProperties: false
+ properties:
+ bucket_start:
+ type: string
+ format: date
+ signups:
+ type: integer
+ format: int64
+ minimum: 0
+ description: Accounts created during the bucket.
+ signins:
+ type: integer
+ format: int64
+ minimum: 0
+ description: Successful session creations during the bucket.
+ is_partial:
+ type: boolean
+ description: Whether the requested window or observation time clips this bucket.
+ required:
+ - bucket_start
+ - signups
+ - signins
+ - is_partial
+ AuthInsightsSummary:
+ type: object
+ additionalProperties: false
+ properties:
+ total_users:
+ type: integer
+ format: int64
+ minimum: 0
+ description: Current auth-user count, matching the auth-user list total.
+ active_users_30d:
+ type: integer
+ format: int64
+ minimum: 0
+ description: Users with a successful session creation or refresh in the trailing 30 days since activity collection was deployed.
+ required:
+ - total_users
+ - active_users_30d
+ AuthInsightsWindow:
+ type: object
+ additionalProperties: false
+ properties:
+ from:
+ type: string
+ format: date
+ to:
+ type: string
+ format: date
+ interval:
+ $ref: '#/components/schemas/AuthInsightsInterval'
+ required:
+ - from
+ - to
+ - interval
+ AuthHostedPage:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ page_type:
+ $ref: '#/components/schemas/HostedAuthPageType'
+ html:
+ type: string
+ description: HTML content for this page type.
+ css:
+ type: string
+ description: CSS content for this page type.
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ AuthHostedPageResponse:
+ type: object
+ required:
+ - page
+ - defaults
+ - runtime
+ properties:
+ page:
+ allOf:
+ - $ref: '#/components/schemas/AuthHostedPage'
+ nullable: true
+ description: The saved page, or null when the project has not customized this page type yet.
+ defaults:
+ $ref: '#/components/schemas/AuthHostedPageDefaults'
+ runtime:
+ $ref: '#/components/schemas/AuthHostedPageRuntime'
+ AuthIdentity:
+ type: object
+ description: |
+ A real email identity owned by the account. One account can own multiple
+ identities (for example a work email plus a personal email linked via OAuth).
+ properties:
+ id:
+ type: string
+ format: uuid
+ description: Unique identity identifier
+ email:
+ type: string
+ format: email
+ description: The email address this identity represents
+ email_verified:
+ type: boolean
+ description: Whether ownership of this email has been verified
+ is_primary:
+ type: boolean
+ description: Whether the account's primary sign-in method resolves to this identity
+ created_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - email
+ - email_verified
+ - is_primary
+ - created_at
+ AuthIdentitiesResponse:
+ type: object
+ properties:
+ identities:
+ type: array
+ items:
+ $ref: '#/components/schemas/AuthIdentity'
+ required:
+ - identities
+ AuthMethodSummary:
+ type: object
+ description: |
+ A single sign-in method the account owns (password, an OAuth provider, or an
+ active anonymous method). `is_primary` reflects the account's primary_method_id.
+ properties:
+ id:
+ type: string
+ format: uuid
+ description: Unique method identifier
+ type:
+ type: string
+ x-go-type: string
+ description: The kind of sign-in method
+ enum:
+ - password
+ - oauth
+ - anonymous
+ provider:
+ type: string
+ description: OAuth provider name; present only when type is oauth
+ example: google
+ identity_id:
+ type: string
+ description: |
+ The identity this method signs in to — a UUID for password/oauth methods,
+ empty for anonymous methods.
+ email:
+ type: string
+ description: The email of the method's identity (empty for anonymous)
+ is_primary:
+ type: boolean
+ description: Whether this is the account's primary sign-in method
+ last_used_at:
+ type: string
+ format: date-time
+ description: When this method was last used to sign in, if ever
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - type
+ - identity_id
+ - email
+ - is_primary
+ - created_at
+ - updated_at
+ AuthMethodsResponse:
+ type: object
+ properties:
+ methods:
+ type: array
+ items:
+ $ref: '#/components/schemas/AuthMethodSummary'
+ required:
+ - methods
+ AuthPasswordPolicy:
+ type: object
+ additionalProperties: false
+ description: Effective backend-enforced password policy.
+ properties:
+ effective_min_length:
+ type: integer
+ minimum: 15
+ maximum: 128
+ description: Effective minimum password length in Unicode characters.
+ min_configurable_length:
+ type: integer
+ minimum: 15
+ maximum: 15
+ description: Lowest minimum password length accepted by the auth configuration endpoint.
+ max_length:
+ type: integer
+ minimum: 128
+ maximum: 128
+ description: Maximum password length in Unicode characters.
+ require_uppercase:
+ type: boolean
+ description: Whether passwords must contain an ASCII uppercase letter (A-Z).
+ require_lowercase:
+ type: boolean
+ description: Whether passwords must contain an ASCII lowercase letter (a-z).
+ require_numbers:
+ type: boolean
+ description: Whether passwords must contain an ASCII digit (0-9).
+ require_special_chars:
+ type: boolean
+ description: Whether passwords must contain one of the backend-supported special characters.
+ compromised_passwords_rejected:
+ type: boolean
+ description: Whether common and known-compromised passwords are rejected by the backend.
+ required:
+ - effective_min_length
+ - min_configurable_length
+ - max_length
+ - require_uppercase
+ - require_lowercase
+ - require_numbers
+ - require_special_chars
+ - compromised_passwords_rejected
+ AuthSession:
+ type: object
+ description: An authentication session for a user
+ properties:
+ id:
+ type: string
+ format: uuid
+ description: Unique session identifier
+ user_id:
+ type: string
+ format: uuid
+ description: The user this session belongs to
+ provider:
+ type: string
+ description: Authentication provider used to create this session
+ enum:
+ - email
+ - google
+ - github
+ - microsoft
+ - apple
+ - anonymous
+ example: email
+ user_agent:
+ type: string
+ description: Browser/device user agent string
+ example: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
+ ip_address:
+ type: string
+ description: IP address of the client when the session was created
+ example: 192.168.1.1
+ last_ip_address:
+ type: string
+ description: IP address of the most recent activity (token refresh)
+ example: 192.168.1.100
+ expires_at:
+ type: string
+ format: date-time
+ description: When this session expires
+ last_activity_at:
+ type: string
+ format: date-time
+ description: Last activity timestamp
+ session_started_at:
+ type: string
+ format: date-time
+ description: When the session was created
+ is_active:
+ type: boolean
+ description: Whether the session is currently active (not expired)
+ is_current:
+ type: boolean
+ description: Whether this is the session making the current request
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - user_id
+ - provider
+ - expires_at
+ - is_active
+ - is_current
+ AuthSignupResponse:
+ type: object
+ description: |
+ Uniform, session-less response returned by POST /auth/signup. It carries no
+ tokens and no user object, and is identical for a new account and for an
+ already-registered email (anti-enumeration). Clients obtain a session with a
+ subsequent POST /auth/signin.
+ properties:
+ confirmation_required:
+ type: boolean
+ description: |
+ Whether the project requires email confirmation. Reflects project config
+ only (identical for a new and an existing email), so it leaks nothing about
+ account existence.
+ message:
+ type: string
+ description: Human-readable acknowledgement.
+ required:
+ - confirmation_required
+ - message
+ AuthTokenResponse:
+ type: object
+ properties:
+ access_token:
+ type: string
+ description: JWT access token (expires after configured lifetime)
+ token_type:
+ type: string
+ example: bearer
+ expires_in:
+ type: integer
+ description: Access token lifetime in seconds
+ refresh_token:
+ type: string
+ x-go-type-skip-optional-pointer: true
+ description: |
+ Long-lived token for getting new access tokens. Omitted when the
+ request uses eligible HttpOnly cookie session storage.
+ user:
+ $ref: '#/components/schemas/AuthUser'
+ required:
+ - access_token
+ - token_type
+ - expires_in
+ - user
+ AuthUser:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ email:
+ type: string
+ format: email
+ email_confirmed:
+ type: boolean
+ user_metadata:
+ type: object
+ additionalProperties: true
+ description: User-editable metadata
+ app_metadata:
+ type: object
+ additionalProperties: true
+ description: Application-controlled metadata (read-only for users)
+ avatar_url:
+ type: string
+ format: uri
+ description: User avatar URL (from OAuth provider or manually set)
+ status:
+ type: string
+ enum:
+ - active
+ - banned
+ - deleted
+ banned_until:
+ type: string
+ format: date-time
+ nullable: true
+ description: When temporary ban expires (null if not banned or permanent)
+ last_sign_in_at:
+ type: string
+ format: date-time
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - email
+ - status
+ BanUserResponse:
+ type: object
+ description: Response when banning a user
+ properties:
+ message:
+ type: string
+ example: User banned until 2026-12-31T23:59:59Z
+ user_id:
+ type: string
+ format: uuid
+ email:
+ type: string
+ format: email
+ status:
+ type: string
+ enum:
+ - banned
+ banned_until:
+ type: string
+ format: date-time
+ nullable: true
+ description: When the ban expires (null for permanent ban)
+ required:
+ - message
+ - user_id
+ - email
+ - status
+ BatchFunctionDeployFailure:
+ type: object
+ properties:
+ name:
+ type: string
+ function_id:
+ type: string
+ format: uuid
+ operation:
+ type: string
+ enum:
+ - deploy
+ - update
+ error:
+ type: string
+ required:
+ - name
+ - error
+ BatchFunctionDeployResponse:
+ type: object
+ properties:
+ batch_id:
+ type: string
+ format: uuid
+ data:
+ type: array
+ description: Functions whose deployment workflows were started successfully
+ items:
+ $ref: '#/components/schemas/Function'
+ failed:
+ type: array
+ description: Functions that failed before their workflow started. Successful functions are left running; failed new functions are deleted and failed updates are rolled back where possible.
+ items:
+ $ref: '#/components/schemas/BatchFunctionDeployFailure'
+ required:
+ - batch_id
+ - data
+ CompleteUploadSessionResponse:
+ type: object
+ description: Response when completing an upload
+ properties:
+ object:
+ $ref: '#/components/schemas/StorageObject'
+ CreateDatabaseBranchRequest:
+ type: object
+ properties:
+ name:
+ type: string
+ description: Branch name (must be unique within the parent database)
+ pattern: ^[a-z0-9_]+$
+ maxLength: 64
+ example: feature_checkout
+ ttl_seconds:
+ type: integer
+ format: int64
+ minimum: 3600
+ maximum: 2592000
+ description: |
+ How long the branch should live, between one hour and 30 days.
+ Defaults to 7 days when omitted.
+ example: 86400
+ required:
+ - name
+ CreateDatabaseRequest:
+ type: object
+ description: |
+ Create a new PostgreSQL database. Volcano automatically sets up:
+ - Auth helpers (auth.uid(), auth.email(), auth.role())
+ - Database roles (anon for unauthenticated, authenticated for signed-in users)
+ - Secure multi-tenant isolation
+ - Ready for Row-Level Security
+ properties:
+ name:
+ type: string
+ description: Database name (must be unique within project)
+ pattern: ^[a-z0-9_]+$
+ maxLength: 64
+ example: my_database
+ region:
+ type: string
+ description: Region for database hosting
+ example: aws-us-east-1
+ enum:
+ - aws-us-east-1
+ - aws-us-east-2
+ - aws-us-west-2
+ - aws-eu-central-1
+ - aws-eu-west-2
+ - aws-ap-southeast-1
+ - aws-ap-southeast-2
+ - aws-sa-east-1
+ pg_version:
+ type: string
+ description: PostgreSQL major version
+ example: '16'
+ enum:
+ - '15'
+ - '16'
+ database_type:
+ type: string
+ description: |
+ Compute size tier (optional, defaults to volcano-db-xs).
+ Determines autoscaling limits for the database.
+ enum:
+ - volcano-db-xs
+ - volcano-db-s
+ - volcano-db-m
+ - volcano-db-l
+ - volcano-db-xl
+ - volcano-db-2xl
+ default: volcano-db-xs
+ example: volcano-db-xs
+ required:
+ - name
+ - region
+ - pg_version
+ CreateEmailTemplateRequest:
+ type: object
+ properties:
+ template_type:
+ type: string
+ enum:
+ - welcome
+ - confirmation
+ - password_reset
+ - password_changed
+ description: Type of email template
+ subject:
+ type: string
+ description: Email subject line
+ example: Confirm your email
+ html_body:
+ type: string
+ description: |
+ HTML template body. Available placeholders:
+ - {{.Token}} - The confirmation/reset token
+ - {{.ProjectName}} - The project name
+ - {{.Email}} - User's email address
+ text_body:
+ type: string
+ description: Plain text template body (same placeholders as HTML)
+ required:
+ - template_type
+ - subject
+ - html_body
+ - text_body
+ CreateFrontendCustomDomainRequest:
+ type: object
+ properties:
+ domain:
+ type: string
+ description: Fully-qualified domain name (hostname only, no scheme/path)
+ example: app.example.com
+ tls:
+ $ref: '#/components/schemas/FrontendCustomDomainTLSConfig'
+ required:
+ - domain
+ - tls
+ CreateFunctionSchedulerRequest:
+ type: object
+ required:
+ - name
+ - schedule
+ properties:
+ name:
+ type: string
+ maxLength: 200
+ enabled:
+ type: boolean
+ default: true
+ schedule:
+ $ref: '#/components/schemas/ScheduleRequest'
+ payload:
+ type: object
+ additionalProperties: true
+ regions:
+ type: array
+ description: Optional single explicit deployed region. If omitted, the scheduler chooses one deployed region and invokes according to the cron expression.
+ maxItems: 1
+ items:
+ type: string
+ CreateOAuthConfigRequest:
+ type: object
+ required:
+ - provider
+ properties:
+ provider:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - device
+ example: google
+ client_id:
+ type: string
+ example: 123456789.apps.googleusercontent.com
+ description: Required for non-device providers. Must not be provided for `provider=device`; server always auto-generates it.
+ client_secret:
+ type: string
+ example: GOCSPX-abc123def456
+ description: Required for non-device providers. Must not be provided for `provider=device`; server always auto-generates it.
+ redirect_url:
+ type: string
+ description: Required for non-device providers. Not used for `provider=device`.
+ format: uri
+ example: https://yourapp.com/auth/callback
+ scopes:
+ type: array
+ items:
+ type: string
+ example:
+ - openid
+ - email
+ - profile
+ description: Optional for non-device providers, uses provider defaults if omitted. Not used for `provider=device`.
+ CreateProjectRequest:
+ type: object
+ description: Request to create a new project
+ properties:
+ name:
+ type: string
+ description: |
+ Project name (must be unique).
+ Can only contain letters, numbers, underscores, and hyphens.
+ pattern: ^[A-Za-z0-9_-]+$
+ minLength: 1
+ maxLength: 255
+ example: my-awesome-app
+ all_regions:
+ type: boolean
+ description: |
+ Optional region policy.
+ - `true` (default): project functions deploy to all configured regions
+ - `false`: project deploys only to `selected_regions`
+ default: true
+ selected_regions:
+ type: array
+ items:
+ type: string
+ description: |
+ Optional region subset. Requires `all_regions=false`.
+ Region names must be a subset of platform `AWS_REGIONS`.
+ example:
+ - us-east-1
+ - us-west-2
+ required:
+ - name
+ CreateStorageBucketRequest:
+ type: object
+ properties:
+ name:
+ type: string
+ description: Bucket name (alphanumeric, dashes, underscores)
+ pattern: ^[a-zA-Z0-9_-]+$
+ minLength: 1
+ maxLength: 64
+ file_size_limit:
+ type: integer
+ format: int64
+ description: Maximum file size in bytes
+ allowed_mime_types:
+ type: array
+ items:
+ type: string
+ description: Allowed MIME types (e.g., ["image/png", "image/jpeg"])
+ required:
+ - name
+ CreateStoragePolicyRequest:
+ type: object
+ properties:
+ name:
+ type: string
+ description: Policy name
+ operation:
+ type: string
+ enum:
+ - SELECT
+ - INSERT
+ - UPDATE
+ - DELETE
+ description: Operation this policy applies to
+ definition:
+ type: string
+ description: Policy expression
+ required:
+ - name
+ - operation
+ - definition
+ CreateUploadSessionRequest:
+ type: object
+ description: Request to create a resumable upload session
+ properties:
+ object_path:
+ type: string
+ description: Target file path within the bucket
+ example: videos/large-file.mp4
+ content_type:
+ type: string
+ description: MIME type of the file
+ example: video/mp4
+ total_size:
+ type: integer
+ format: int64
+ description: Total file size in bytes (max 5TB)
+ minimum: 1
+ maximum: 5497558138880
+ example: 5368709120
+ part_size:
+ type: integer
+ format: int64
+ description: 'Part size in bytes (default: 25MB, min: 5MB, max: 25MB)'
+ minimum: 5242880
+ maximum: 26214400
+ example: 26214400
+ required:
+ - object_path
+ - content_type
+ - total_size
+ CreateUploadSessionResponse:
+ type: object
+ description: Response when creating an upload session
+ properties:
+ session_id:
+ type: string
+ description: Upload session ID
+ example: session-abc123
+ part_size:
+ type: integer
+ format: int64
+ description: Actual part size to use
+ example: 26214400
+ total_parts:
+ type: integer
+ description: Number of parts to upload
+ example: 52
+ expires_at:
+ type: string
+ format: date-time
+ description: When the session expires (7 days from creation)
+ example: '2024-01-22T10:30:00Z'
+ CreateVariableRequest:
+ type: object
+ properties:
+ name:
+ type: string
+ minLength: 1
+ maxLength: 256
+ pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
+ value:
+ type: string
+ required:
+ - name
+ - value
+ Database:
+ type: object
+ description: |
+ PostgreSQL database with automatic scalability and security features.
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ description: Database name
+ pattern: ^[a-z0-9_]+$
+ maxLength: 64
+ status:
+ type: string
+ enum:
+ - provisioning
+ - active
+ - failed
+ - deleting
+ description: Database provisioning status
+ provisioning_started_at:
+ type: string
+ format: date-time
+ description: Timestamp when the current provisioning phase started
+ connection_string:
+ type: string
+ description: |
+ Secure PostgreSQL connection URI for your database.
+
+ The database is identified by the globally-unique username
+ (`volcano_client_{database_id}`) already in this URI; the
+ `application_name` parameter only selects the access mode:
+ - `volcano_full_access` — Full admin access (DDL, migrations)
+ - `volcano_user_access:{user_id}` — User impersonation (RLS enforced)
+ - `volcano_user_access` — Anonymous access (anon role, RLS enforced)
+ region:
+ type: string
+ description: Region where the database is hosted
+ example: aws-us-east-1
+ pg_version:
+ type: string
+ description: PostgreSQL major version
+ example: '16'
+ database_type:
+ type: string
+ description: |
+ Database size tier that determines available RAM and scaling limits.
+ enum:
+ - volcano-db-xs
+ - volcano-db-s
+ - volcano-db-m
+ - volcano-db-l
+ - volcano-db-xl
+ - volcano-db-2xl
+ example: volcano-db-xs
+ storage_bytes:
+ type: integer
+ format: int64
+ minimum: 0
+ description: |
+ Latest observed on-disk size from `pg_database_size`, in bytes. This
+ point-in-time gauge may be absent until the database has been sampled.
+ Summing the latest samples for every database in a project produces
+ the project's "Database Storage (Bytes)" usage gauge. Populated on
+ database list responses; single-database responses omit it.
+ last_invoked_at:
+ type: string
+ format: date-time
+ description: Most recent request timestamp for this database
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - project_id
+ - name
+ - status
+ - created_at
+ - updated_at
+ DatabaseBranch:
+ type: object
+ description: |
+ A copy-on-write fork of a database, for development and testing.
+
+ A branch starts as an exact copy of its parent's data and diverges from
+ there. It has its own connection string and its own credential, so a
+ branch password cannot reach the parent.
+
+ Every branch expires. `expires_at` is a hard deadline: once it passes the
+ branch stops accepting connections and is deleted. Use `PATCH` to extend
+ a branch you are still working on.
+ properties:
+ id:
+ type: string
+ format: uuid
+ database_id:
+ type: string
+ format: uuid
+ description: The parent database this branch was forked from.
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ description: Branch name, unique within the parent database.
+ pattern: ^[a-z0-9_]+$
+ maxLength: 64
+ status:
+ type: string
+ enum:
+ - provisioning
+ - active
+ - failed
+ - deleting
+ description: |
+ Branch status. A new branch starts `provisioning` and is not
+ connectable until it reports `active`; poll this endpoint until it
+ does. `connection_string` is only present while `active`.
+
+ `provisioning` also covers a branch being rebuilt after a `reset`,
+ and a build that is between retries, so it is the status to keep
+ waiting on. `failed` is terminal: it means the platform gave up, and
+ the branch will not become `active` on its own.
+ connection_string:
+ type: string
+ description: |
+ PostgreSQL connection URI for this branch. Present only while the
+ branch is `active`.
+
+ The URI carries the branch's own globally-unique username and
+ password; `application_name` selects the access mode exactly as it
+ does for the parent database:
+ - `volcano_full_access` — Full admin access (DDL, migrations)
+ - `volcano_user_access:{user_id}` — User impersonation (RLS enforced)
+ - `volcano_user_access` — Anonymous access (anon role, RLS enforced)
+ ttl_seconds:
+ type: integer
+ format: int64
+ minimum: 1
+ description: |
+ The lifetime the branch was created with. Resetting a branch re-arms
+ this same duration, so a reset never shortens a branch's remaining
+ life.
+ expires_at:
+ type: string
+ format: date-time
+ description: |
+ When the branch stops serving connections and becomes eligible for
+ deletion. Enforced on the connection path, so it holds even if
+ reclamation is delayed.
+ storage_bytes:
+ type: integer
+ format: int64
+ minimum: 0
+ description: |
+ Bytes this branch has diverged from its parent, which is what a
+ branch actually costs. Shared pages are not counted twice. Counts
+ against the parent database's storage allowance. Absent until the
+ branch has been sampled.
+ last_invoked_at:
+ type: string
+ format: date-time
+ description: Most recent request timestamp for this branch
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - database_id
+ - project_id
+ - name
+ - status
+ - ttl_seconds
+ - expires_at
+ - created_at
+ - updated_at
+ DatabaseBranchList:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/DatabaseBranch'
+ required:
+ - data
+ DatabaseBranchStorage:
+ type: object
+ description: One branch's contribution to its parent database's storage.
+ properties:
+ id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ description: Branch name
+ storage_bytes:
+ type: integer
+ format: int64
+ minimum: 0
+ description: |
+ Bytes this branch has diverged from its parent. Pages the branch
+ still shares with the parent are not counted, so this is what the
+ branch actually adds to the total rather than its apparent size.
+ required:
+ - id
+ - name
+ - storage_bytes
+ DatabaseSelectRequest:
+ type: object
+ properties:
+ table:
+ type: string
+ description: Table name to query
+ example: posts
+ select:
+ type: array
+ items:
+ type: string
+ description: Columns to select (omit for *)
+ example:
+ - id
+ - title
+ - content
+ - created_at
+ filters:
+ type: array
+ items:
+ $ref: '#/components/schemas/DatabaseQueryFilter'
+ description: WHERE conditions (combined with AND)
+ example:
+ - column: status
+ operator: eq
+ value: published
+ - column: views
+ operator: gt
+ value: 100
+ order:
+ type: array
+ items:
+ $ref: '#/components/schemas/DatabaseQueryOrder'
+ description: ORDER BY clauses
+ example:
+ - column: created_at
+ ascending: false
+ limit:
+ type: integer
+ minimum: 1
+ maximum: 1000
+ description: Maximum rows to return
+ example: 10
+ offset:
+ type: integer
+ minimum: 0
+ description: Number of rows to skip (for pagination)
+ example: 0
+ required:
+ - table
+ DatabaseInsertRequest:
+ type: object
+ properties:
+ table:
+ type: string
+ description: Table name
+ example: posts
+ values:
+ type: object
+ additionalProperties: true
+ description: Column values to insert
+ example:
+ title: My New Post
+ content: This is the content
+ status: draft
+ required:
+ - table
+ - values
+ DatabaseUpdateRequest:
+ type: object
+ properties:
+ table:
+ type: string
+ description: Table name
+ example: posts
+ values:
+ type: object
+ additionalProperties: true
+ description: Column values to update
+ example:
+ title: Updated Title
+ status: published
+ filters:
+ type: array
+ minItems: 1
+ items:
+ $ref: '#/components/schemas/DatabaseQueryFilter'
+ description: |
+ WHERE conditions for which rows to update. At least one filter is
+ required; a filterless update is rejected to avoid rewriting every
+ row.
+ example:
+ - column: id
+ operator: eq
+ value: post-uuid
+ required:
+ - table
+ - values
+ - filters
+ DatabaseDeleteRequest:
+ type: object
+ properties:
+ table:
+ type: string
+ description: Table name
+ example: posts
+ filters:
+ type: array
+ minItems: 1
+ items:
+ $ref: '#/components/schemas/DatabaseQueryFilter'
+ description: WHERE conditions (required for safety)
+ example:
+ - column: id
+ operator: eq
+ value: post-uuid
+ required:
+ - table
+ - filters
+ DatabaseQueryResult:
+ type: object
+ description: |
+ Rows returned by a data API request. RLS-filtered unless the request was
+ made with a service key.
+ properties:
+ data:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ description: Result rows
+ count:
+ type: integer
+ description: Number of rows returned
+ DatabaseStats:
+ type: object
+ properties:
+ current_storage_bytes:
+ type: integer
+ format: int64
+ minimum: 0
+ description: |
+ On-disk size right now, in bytes: the database itself plus every
+ branch's divergence from it. This is the figure the storage
+ allowance is enforced against. `branches` breaks it down.
+ current_storage_mb:
+ type: number
+ format: double
+ minimum: 0
+ description: '`current_storage_bytes` expressed in megabytes.'
+ branches:
+ type: array
+ description: |
+ Per-branch contribution to `current_storage_bytes`. Empty when the
+ database has no branches. A branch that has not diverged from its
+ parent contributes nothing.
+ items:
+ $ref: '#/components/schemas/DatabaseBranchStorage'
+ storage_bytes:
+ type: integer
+ format: int64
+ description: Total storage used in bytes (data + WAL)
+ data_written_bytes:
+ type: integer
+ format: int64
+ description: Total data written in bytes
+ data_transfer_bytes:
+ type: integer
+ format: int64
+ description: Total data transferred in bytes
+ compute_time_seconds:
+ type: number
+ format: double
+ description: Total CPU seconds consumed
+ active_time_seconds:
+ type: number
+ format: double
+ description: Total active compute time in seconds
+ time_range:
+ type: string
+ description: Time range of the metrics (e.g., "2024-01-01T00:00:00Z to 2024-01-02T00:00:00Z")
+ granularity:
+ type: string
+ enum:
+ - hourly
+ - daily
+ - monthly
+ description: Granularity of the aggregated metrics
+ required:
+ - current_storage_bytes
+ - current_storage_mb
+ - storage_bytes
+ - data_written_bytes
+ - data_transfer_bytes
+ - compute_time_seconds
+ - active_time_seconds
+ DatabaseQueryPerformanceResponse:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/DatabaseQueryPerformanceItem'
+ required:
+ - data
+ UpdateDatabaseBranchRequest:
+ type: object
+ description: Replace the branch's lifetime and restart its countdown from now.
+ properties:
+ ttl_seconds:
+ type: integer
+ format: int64
+ minimum: 3600
+ maximum: 2592000
+ description: The new lifetime, between one hour and 30 days.
+ example: 86400
+ required:
+ - ttl_seconds
+ DeviceAuthorizationResponse:
+ type: object
+ properties:
+ device_code:
+ type: string
+ user_code:
+ type: string
+ verification_uri:
+ type: string
+ description: |
+ Browser verification URL. Points at the project's managed device
+ approval page served by this API:
+ `/projects/{projectId}/auth/hosted?action=device&anon_key=...`.
+ Requires the project to have managed auth enabled and a default anon
+ key. A custom CLI may ignore this and direct users to its own
+ RFC 8628-compatible page instead (see the device-auth guide).
+ verification_uri_complete:
+ type: string
+ description: |
+ Same as `verification_uri` but with the `user_code` prefilled
+ (`&user_code=...`). This is the URL most device clients open.
+ expires_in:
+ type: integer
+ interval:
+ type: integer
+ required:
+ - device_code
+ - user_code
+ - verification_uri
+ - verification_uri_complete
+ - expires_in
+ - interval
+ EmailTemplate:
+ type: object
+ description: Custom email template
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ template_type:
+ type: string
+ enum:
+ - welcome
+ - confirmation
+ - password_reset
+ - password_changed
+ subject:
+ type: string
+ example: Confirm your email address
+ html_body:
+ type: string
+ description: HTML template with placeholders
+ text_body:
+ type: string
+ description: Plain text template with placeholders
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - template_type
+ - subject
+ - html_body
+ - text_body
+ Error:
+ type: object
+ properties:
+ error:
+ type: string
+ code:
+ type: string
+ description: Stable machine-readable error code when a specific recovery path is available.
+ required:
+ - error
+ ImportProvider:
+ type: string
+ enum:
+ - vercel
+ default: vercel
+ x-enum-varnames:
+ - ImportProviderVercel
+ ImportConnectStartResponse:
+ type: object
+ properties:
+ authorization_url:
+ type: string
+ required:
+ - authorization_url
+ ImportConnection:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ provider:
+ $ref: '#/components/schemas/ImportProvider'
+ account_id:
+ type: string
+ account_name:
+ type: string
+ configuration_id:
+ type: string
+ granted_scopes:
+ type: array
+ items:
+ type: string
+ status:
+ type: string
+ expires_at:
+ type: string
+ format: date-time
+ nullable: true
+ last_authenticated_at:
+ type: string
+ format: date-time
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - provider
+ - account_id
+ - account_name
+ - configuration_id
+ - granted_scopes
+ - status
+ - last_authenticated_at
+ - created_at
+ - updated_at
+ ImportConnectionsResponse:
+ type: object
+ properties:
+ connections:
+ type: array
+ items:
+ $ref: '#/components/schemas/ImportConnection'
+ required:
+ - connections
+ ImportSource:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ account_id:
+ type: string
+ framework:
+ type: string
+ required:
+ - id
+ - name
+ - account_id
+ - framework
+ ImportSourcesResponse:
+ type: object
+ properties:
+ sources:
+ type: array
+ items:
+ $ref: '#/components/schemas/ImportSource'
+ required:
+ - sources
+ ProjectImportTarget:
+ type: string
+ enum:
+ - production
+ x-enum-varnames:
+ - ProjectImportTargetProduction
+ ProjectImportDestinationMode:
+ type: string
+ enum:
+ - create
+ x-enum-varnames:
+ - ProjectImportDestinationCreate
+ ProjectImportDisposition:
+ type: string
+ enum:
+ - automatic
+ - manual
+ - deferred
+ - unsupported
+ x-enum-varnames:
+ - ProjectImportDispositionAutomatic
+ - ProjectImportDispositionManual
+ - ProjectImportDispositionDeferred
+ - ProjectImportDispositionUnsupported
+ ProjectImportImpact:
+ type: string
+ enum:
+ - none
+ - warning
+ - blocking
+ x-enum-varnames:
+ - ProjectImportImpactNone
+ - ProjectImportImpactWarning
+ - ProjectImportImpactBlocking
+ ProjectImportReadiness:
+ type: string
+ enum:
+ - importable
+ - needs_input
+ - blocked
+ x-enum-varnames:
+ - ProjectImportReadinessImportable
+ - ProjectImportReadinessNeedsInput
+ - ProjectImportReadinessBlocked
+ ProjectImportActionCode:
+ type: string
+ enum:
+ - project.create
+ - git.connect
+ - frontend.configure
+ - variable.set
+ x-enum-varnames:
+ - ProjectImportActionProjectCreate
+ - ProjectImportActionGitConnect
+ - ProjectImportActionFrontendConfigure
+ - ProjectImportActionVariableSet
+ ProjectImportResourceKind:
+ type: string
+ enum:
+ - project
+ - git_repository
+ - frontend
+ - variable
+ - domain
+ x-enum-varnames:
+ - ProjectImportResourceProject
+ - ProjectImportResourceGitRepository
+ - ProjectImportResourceFrontend
+ - ProjectImportResourceVariable
+ - ProjectImportResourceDomain
+ ProjectImportPreflightRequest:
+ type: object
+ properties:
+ connection_id:
+ type: string
+ format: uuid
+ source_id:
+ type: string
+ minLength: 1
+ project_name:
+ type: string
+ maxLength: 255
+ pattern: ^[A-Za-z0-9_-]+$
+ target:
+ $ref: '#/components/schemas/ProjectImportTarget'
+ confirm_environment_variable_read:
+ type: boolean
+ default: false
+ description: Set to true only after the user confirms an immediately preceding disclosure that the Vercel Integration grant permits reads and writes, while this preflight reads production variable values only. When false or omitted, preflight reads variable metadata only and reports readable values as manual input.
+ required:
+ - connection_id
+ - source_id
+ - project_name
+ - target
+ ProjectImportStartRequest:
+ type: object
+ properties:
+ connection_id:
+ type: string
+ format: uuid
+ source_id:
+ type: string
+ minLength: 1
+ maxLength: 255
+ project_name:
+ type: string
+ maxLength: 255
+ pattern: ^[A-Za-z0-9_-]+$
+ target:
+ $ref: '#/components/schemas/ProjectImportTarget'
+ confirm_environment_variable_read:
+ type: boolean
+ enum:
+ - true
+ preflight_fingerprint:
+ type: string
+ pattern: ^sha256:[0-9a-f]{64}$
+ required:
+ - connection_id
+ - source_id
+ - project_name
+ - target
+ - confirm_environment_variable_read
+ - preflight_fingerprint
+ ProjectImportRunStatus:
+ type: string
+ enum:
+ - pending
+ - running
+ - succeeded
+ - failed
+ - superseded
+ x-enum-varnames:
+ - ProjectImportRunStatusPending
+ - ProjectImportRunStatusRunning
+ - ProjectImportRunStatusSucceeded
+ - ProjectImportRunStatusFailed
+ - ProjectImportRunStatusSuperseded
+ ProjectImportRun:
+ type: object
+ properties:
+ id:
+ type: string
+ provider:
+ $ref: '#/components/schemas/ImportProvider'
+ source_id:
+ type: string
+ destination_project_name:
+ type: string
+ resource:
+ $ref: '#/components/schemas/ResourceReference'
+ deployment:
+ $ref: '#/components/schemas/DeploymentReference'
+ status:
+ $ref: '#/components/schemas/ProjectImportRunStatus'
+ error_code:
+ type: string
+ error_message:
+ type: string
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - provider
+ - source_id
+ - destination_project_name
+ - resource
+ - deployment
+ - status
+ - created_at
+ - updated_at
+ ProjectImportDestination:
+ type: object
+ properties:
+ mode:
+ $ref: '#/components/schemas/ProjectImportDestinationMode'
+ project_name:
+ type: string
+ target:
+ $ref: '#/components/schemas/ProjectImportTarget'
+ required:
+ - mode
+ - project_name
+ - target
+ ProjectImportResource:
+ type: object
+ properties:
+ kind:
+ $ref: '#/components/schemas/ProjectImportResourceKind'
+ name:
+ type: string
+ source_id:
+ type: string
+ minLength: 1
+ description: Stable provider identifier for a scoped source resource.
+ scope:
+ type: string
+ minLength: 1
+ description: URL-encoded source scope, including target, branch, and custom environment identifiers.
+ required:
+ - kind
+ - name
+ ProjectImportAction:
+ type: object
+ properties:
+ code:
+ $ref: '#/components/schemas/ProjectImportActionCode'
+ resource:
+ $ref: '#/components/schemas/ProjectImportResource'
+ disposition:
+ $ref: '#/components/schemas/ProjectImportDisposition'
+ required:
+ - code
+ - resource
+ - disposition
+ ProjectImportFinding:
+ type: object
+ properties:
+ code:
+ type: string
+ pattern: ^(vercel|volcano|import)\.[a-z0-9_]+$
+ resource:
+ $ref: '#/components/schemas/ProjectImportResource'
+ disposition:
+ $ref: '#/components/schemas/ProjectImportDisposition'
+ impact:
+ $ref: '#/components/schemas/ProjectImportImpact'
+ message:
+ type: string
+ remediation:
+ type: string
+ required:
+ - code
+ - resource
+ - disposition
+ - impact
+ - message
+ - remediation
+ ProjectImportSummary:
+ type: object
+ properties:
+ automatic:
+ type: integer
+ minimum: 0
+ manual:
+ type: integer
+ minimum: 0
+ deferred:
+ type: integer
+ minimum: 0
+ unsupported:
+ type: integer
+ minimum: 0
+ warnings:
+ type: integer
+ minimum: 0
+ blocking:
+ type: integer
+ minimum: 0
+ required:
+ - automatic
+ - manual
+ - deferred
+ - unsupported
+ - warnings
+ - blocking
+ ProjectImportReport:
+ type: object
+ properties:
+ schema_version:
+ type: string
+ provider:
+ $ref: '#/components/schemas/ImportProvider'
+ source:
+ $ref: '#/components/schemas/ImportSource'
+ destination:
+ $ref: '#/components/schemas/ProjectImportDestination'
+ actions:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectImportAction'
+ findings:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectImportFinding'
+ summary:
+ $ref: '#/components/schemas/ProjectImportSummary'
+ readiness:
+ $ref: '#/components/schemas/ProjectImportReadiness'
+ source_fingerprint:
+ type: string
+ capability_fingerprint:
+ type: string
+ fingerprint:
+ type: string
+ generated_at:
+ type: string
+ format: date-time
+ required:
+ - schema_version
+ - provider
+ - source
+ - destination
+ - actions
+ - findings
+ - summary
+ - readiness
+ - source_fingerprint
+ - capability_fingerprint
+ - fingerprint
+ - generated_at
+ GitConnection:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ provider:
+ type: string
+ provider_user_id:
+ type: string
+ provider_login:
+ type: string
+ status:
+ type: string
+ last_authenticated_at:
+ type: string
+ format: date-time
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - provider
+ - provider_user_id
+ - provider_login
+ - status
+ - last_authenticated_at
+ - created_at
+ - updated_at
+ GitConnectStartResponse:
+ type: object
+ properties:
+ authorization_url:
+ type: string
+ required:
+ - authorization_url
+ GitConnectionsResponse:
+ type: object
+ properties:
+ connections:
+ type: array
+ items:
+ $ref: '#/components/schemas/GitConnection'
+ required:
+ - connections
+ GitInstallation:
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ account_login:
+ type: string
+ account_type:
+ type: string
+ repository_selection:
+ type: string
+ required:
+ - id
+ - account_login
+ - account_type
+ - repository_selection
+ GitInstallationsResponse:
+ type: object
+ properties:
+ installations:
+ type: array
+ items:
+ $ref: '#/components/schemas/GitInstallation'
+ required:
+ - installations
+ GitRepository:
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ description: Stable GitHub repository id (repository.id), unchanged by renames.
+ full_name:
+ type: string
+ default_branch:
+ type: string
+ private:
+ type: boolean
+ required:
+ - id
+ - full_name
+ - default_branch
+ - private
+ GitRepositoriesResponse:
+ type: object
+ properties:
+ repositories:
+ type: array
+ items:
+ $ref: '#/components/schemas/GitRepository'
+ required:
+ - repositories
+ ProjectGitConnection:
+ type: object
+ properties:
+ repo_installation_id:
+ type: integer
+ format: int64
+ repo_id:
+ type: integer
+ format: int64
+ description: Stable GitHub repository id (repository.id), the authoritative binding.
+ repo_full_name:
+ type: string
+ root_directory:
+ type: string
+ production_branch:
+ type: string
+ description: The branch a push must land on to deploy. Follows the repository's GitHub default branch unless the project set its own, which a default-branch rename on GitHub then leaves alone.
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - repo_installation_id
+ - repo_id
+ - repo_full_name
+ - root_directory
+ - production_branch
+ - updated_at
+ ProjectGitDeploySettings:
+ type: object
+ description: 'A project''s GitHub auto-deploy settings: what a push to the connected repo''s production branch deploys. All settings are default-off.'
+ properties:
+ auto_deploy_enabled:
+ type: boolean
+ description: Whether a production-branch push triggers a deployment.
+ deploy_functions:
+ type: boolean
+ description: Whether the repo's functions are deployed on push.
+ frontend_name:
+ type: string
+ description: Name of the frontend to build and deploy on push. Omitted when no frontend is deployed. Resolved at deploy time; need not exist yet.
+ frontend_app_root:
+ type: string
+ description: App root (subdirectory) the frontend builds from. Omitted for the repo root.
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - auto_deploy_enabled
+ - deploy_functions
+ - updated_at
+ UpdateProjectGitDeploySettingsRequest:
+ type: object
+ description: Full replace of a project's Git auto-deploy settings.
+ properties:
+ auto_deploy_enabled:
+ type: boolean
+ deploy_functions:
+ type: boolean
+ frontend_name:
+ type: string
+ description: Frontend to deploy on push. Omit or empty to deploy no frontend.
+ frontend_app_root:
+ type: string
+ description: App root the frontend builds from. Requires frontend_name; omit for the repo root.
+ required:
+ - auto_deploy_enabled
+ - deploy_functions
+ ProjectLockLeaseRequest:
+ type: object
+ additionalProperties: false
+ properties:
+ ttl_seconds:
+ type: integer
+ minimum: 5
+ maximum: 7776000
+ description: |
+ Lease duration in seconds, from 5 seconds through 90 days, measured
+ from when the request is served. Renew before it elapses. A renewal
+ sets the new expiry outright, so a shorter TTL shortens the lease.
+ Renewals cannot extend an acquisition beyond its absolute 90-day
+ deadline.
+ required:
+ - ttl_seconds
+ ProjectLockLease:
+ type: object
+ additionalProperties: false
+ properties:
+ expires_at:
+ type: string
+ format: date-time
+ description: Advisory lease expiry timestamp in UTC.
+ fencing_token:
+ type: integer
+ format: int64
+ description: |
+ Monotonically increasing token for this acquisition. It rises whenever the
+ lock changes hands and stays the same across renewals of one lease. Pass it
+ to the resource you are protecting and reject any write carrying a token
+ lower than the highest already seen; that is what stops a displaced holder
+ from writing after its lease lapsed.
+ required:
+ - expires_at
+ - fencing_token
+ ProjectLockState:
+ type: object
+ additionalProperties: false
+ properties:
+ held:
+ type: boolean
+ description: |
+ Whether the lock is unavailable right now. False means an acquire would
+ succeed. It remains true during the brief grace window after expiry.
+ expires_at:
+ type: string
+ format: date-time
+ description: Advisory lease expiry timestamp in UTC. Present only when held.
+ fencing_token:
+ type: integer
+ format: int64
+ description: Current holder's fencing token. Present only when held.
+ required:
+ - held
+ SetProjectGitProductionBranchRequest:
+ type: object
+ properties:
+ production_branch:
+ type: string
+ minLength: 1
+ maxLength: 255
+ description: The branch a push must land on to deploy. Validated as a Git branch name only — it does not have to exist yet.
+ required:
+ - production_branch
+ ConnectProjectGitRequest:
+ type: object
+ properties:
+ connection_id:
+ type: string
+ format: uuid
+ description: The caller's user_git_connections row (see /user/git/connections).
+ installation_id:
+ type: integer
+ format: int64
+ repository_id:
+ type: integer
+ format: int64
+ description: Stable GitHub repository id (repository.id), the preferred selector. Either repository_id or repo_full_name is required; when both are given they must identify the same live repository.
+ repo_full_name:
+ type: string
+ deprecated: true
+ description: Deprecated selector kept for a compatibility window; prefer repository_id. Either repository_id or repo_full_name is required.
+ root_directory:
+ type: string
+ description: Monorepo subdirectory the project builds from. Omit for the repo root.
+ production_branch:
+ type: string
+ maxLength: 255
+ description: 'The branch a push must land on to deploy, with three cases, because this is a full replace and a read-modify-write client sends back whatever it read. Omit it to follow the repository''s GitHub default branch, which also discards a branch set earlier. Send back the branch the project already deploys from, when that is the repository''s default, and nothing changes either way — a project pinned to that branch stays pinned. Sending the default branch when the project deploys from something else returns it to following the default, including on a rebind, where a pin describes a branch chosen for the repository being left. Any other branch becomes the project''s own choice, exempt from later default-branch renames. Validated as a Git branch name only: it does not have to exist yet, so a project can be pointed at a branch about to be pushed. Changing repository and naming a branch other than the new repository''s default in one request is refused with 400, because the branch named is almost always the previous repository''s, echoed back — connect first, then set the branch.'
+ required:
+ - connection_id
+ - installation_id
+ Frontend:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ maxLength: 63
+ pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
+ framework:
+ type: string
+ enum:
+ - nextjs
+ app_root:
+ type: string
+ maxLength: 1024
+ description: Optional relative POSIX path from the uploaded archive root to the Next.js app that is deployed.
+ status:
+ type: string
+ description: |
+ Frontend lifecycle status. `degraded` means the regional runtime remains
+ available but edge synchronization exhausted its immediate retries; Volcano
+ retries edge recovery without rebuilding the frontend, and stops once a new
+ deployment is queued or the retry budget runs out, leaving the frontend
+ `degraded` until the next redeploy. A redeploy that fails over a serving
+ frontend stays `active` on the previous deployment, so `failed` means no
+ deployment is serving.
+ enum:
+ - provisioning
+ - active
+ - degraded
+ - failed
+ - deleting
+ provisioning_started_at:
+ type: string
+ format: date-time
+ description: Timestamp when the current provisioning phase started
+ deployed_regions:
+ type: array
+ items:
+ type: string
+ current_deployment_id:
+ type: string
+ format: uuid
+ description: Identifier of the latest frontend deployment operation
+ pending_deployment_id:
+ type: string
+ format: uuid
+ description: Newest queued deployment that will run after the current operation
+ site_url:
+ type: string
+ custom_domain:
+ type: string
+ description: Active custom domain hostname when configured
+ custom_domain_status:
+ type: string
+ description: Current custom domain lifecycle status
+ enum:
+ - pending_verification
+ - provisioning
+ - active
+ - detaching
+ - failed
+ - deleted
+ last_invoked_at:
+ type: string
+ format: date-time
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - project_id
+ - name
+ - framework
+ - status
+ - deployed_regions
+ - created_at
+ - updated_at
+ FrontendCustomDomainResponse:
+ type: object
+ properties:
+ domain:
+ type: string
+ tls_mode:
+ type: string
+ enum:
+ - managed
+ - byoc
+ domain_status:
+ type: string
+ enum:
+ - pending_verification
+ - provisioning
+ - active
+ - detaching
+ - failed
+ - deleted
+ verification_status:
+ type: string
+ enum:
+ - pending
+ - verified
+ verification_records:
+ type: array
+ items:
+ $ref: '#/components/schemas/FrontendDomainVerificationRecord'
+ required_routing_record:
+ $ref: '#/components/schemas/FrontendDomainRoutingRecord'
+ effective_urls:
+ type: array
+ items:
+ type: string
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - domain
+ - tls_mode
+ - domain_status
+ - verification_status
+ - effective_urls
+ - created_at
+ - updated_at
+ FrontendCustomDomainTLSConfig:
+ type: object
+ properties:
+ mode:
+ type: string
+ enum:
+ - byoc
+ default: byoc
+ description: BYOC is mandatory for custom domain creation.
+ certificate_pem:
+ type: string
+ description: Required. PEM-encoded certificate.
+ private_key_pem:
+ type: string
+ description: Required. PEM-encoded private key.
+ certificate_chain_pem:
+ type: string
+ description: Optional PEM-encoded certificate chain.
+ required:
+ - mode
+ - certificate_pem
+ - private_key_pem
+ FrontendDeployment:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ frontend_id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ operation:
+ type: string
+ enum:
+ - deploy
+ - redeploy
+ - delete
+ status:
+ type: string
+ description: |
+ Deployment lifecycle status. A `degraded` redeploy remains available while
+ edge-only recovery is retried. A `failed` redeploy is recorded here while the
+ frontend keeps serving its previous deployment.
+ enum:
+ - queued
+ - provisioning
+ - active
+ - degraded
+ - failed
+ - superseded
+ - deleting
+ - deleted
+ deploy_source:
+ type: string
+ enum:
+ - git
+ - cli
+ - web
+ - api
+ - system
+ - unknown
+ description: What initiated this deployment.
+ initiated_by:
+ type: string
+ description: Platform user that triggered a request-initiated deployment; absent for git and system deployments.
+ artifact_bucket:
+ type: string
+ artifact_key:
+ type: string
+ artifact_version:
+ type: string
+ site_url:
+ type: string
+ cloudformation_stack_id:
+ type: string
+ cloudformation_stack_url:
+ type: string
+ codebuild_duration_seconds:
+ type: integer
+ format: int64
+ description: Total CodeBuild build duration recorded for this deployment, in seconds.
+ codebuild_build_count:
+ type: integer
+ description: Number of completed CodeBuild builds included in codebuild_duration_seconds.
+ codebuild_duration_recorded_at:
+ type: string
+ format: date-time
+ progress:
+ $ref: '#/components/schemas/DeploymentProgress'
+ error_message:
+ type: string
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - frontend_id
+ - project_id
+ - operation
+ - status
+ - deploy_source
+ - created_at
+ - updated_at
+ FrontendDomainRoutingRecord:
+ type: object
+ properties:
+ record_type:
+ type: string
+ enum:
+ - CNAME
+ name:
+ type: string
+ value:
+ type: string
+ required:
+ - record_type
+ - name
+ - value
+ FrontendDomainVerificationRecord:
+ type: object
+ properties:
+ name:
+ type: string
+ type:
+ type: string
+ value:
+ type: string
+ required:
+ - name
+ - type
+ - value
+ FrontendUsageDailyEntry:
+ type: object
+ description: One day of request and error counts for a single frontend.
+ properties:
+ day:
+ type: string
+ format: date
+ description: UTC date (YYYY-MM-DD) the counts cover.
+ requests:
+ type: integer
+ format: int64
+ description: Total requests served on this day.
+ errors:
+ type: integer
+ format: int64
+ description: 5xx responses served on this day.
+ page_views:
+ type: integer
+ format: int64
+ description: Navigable-document responses served on this day (text/html or Sec-Fetch-Dest=document) — strict subset of `requests`.
+ required:
+ - day
+ - requests
+ - errors
+ - page_views
+ FrontendUsageData:
+ type: object
+ description: Monthly frontend request totals grouped by frontend.
+ properties:
+ frontend_id:
+ type: string
+ format: uuid
+ description: Frontend ID
+ frontend_name:
+ type: string
+ description: Frontend name at the time usage was fetched
+ nullable: true
+ requests:
+ type: integer
+ format: int64
+ description: Total requests for this frontend in the current usage month
+ required:
+ - frontend_id
+ - requests
+ FrontendUsageHistoryResponse:
+ type: object
+ description: Zero-filled daily series of request + error counts for a single frontend, oldest first.
+ properties:
+ frontend_id:
+ type: string
+ format: uuid
+ days:
+ type: integer
+ description: Number of daily entries returned (always equal to the `days` query param after clamping).
+ daily:
+ type: array
+ items:
+ $ref: '#/components/schemas/FrontendUsageDailyEntry'
+ total_requests:
+ type: integer
+ format: int64
+ total_errors:
+ type: integer
+ format: int64
+ total_page_views:
+ type: integer
+ format: int64
+ required:
+ - frontend_id
+ - days
+ - daily
+ - total_requests
+ - total_errors
+ - total_page_views
+ Function:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ maxLength: 63
+ pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
+ status:
+ type: string
+ enum:
+ - provisioning
+ - active
+ - failed
+ - deleting
+ provisioning_started_at:
+ type: string
+ format: date-time
+ description: Timestamp when the current provisioning phase started
+ is_public:
+ type: boolean
+ description: |
+ Function visibility for anon-key invocation.
+ - `false` (default): only auth user tokens and service keys can invoke
+ - `true`: anon keys with `functions.invoke` can invoke
+ aws_function_arn:
+ type: string
+ invoke_url:
+ type: string
+ description: Canonical GeoDNS endpoint URL for invoking this function (always HTTPS)
+ deployed_regions:
+ type: array
+ items:
+ type: string
+ description: Regions where this function is currently deployed
+ runtime:
+ type: string
+ handler:
+ type: string
+ current_deployment_id:
+ type: string
+ format: uuid
+ description: Identifier of the latest function deployment operation
+ pending_deployment_id:
+ type: string
+ format: uuid
+ description: Newest queued deployment that will run after the current operation
+ last_invoked_at:
+ type: string
+ format: date-time
+ description: Most recent successful invocation timestamp
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - project_id
+ - name
+ - status
+ - is_public
+ - deployed_regions
+ - created_at
+ - updated_at
+ FunctionDeployment:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ function_id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ batch_id:
+ type: string
+ format: uuid
+ operation:
+ type: string
+ enum:
+ - deploy
+ - update
+ - delete
+ status:
+ type: string
+ enum:
+ - queued
+ - provisioning
+ - active
+ - failed
+ - superseded
+ - deleting
+ - deleted
+ deploy_source:
+ type: string
+ enum:
+ - git
+ - cli
+ - web
+ - api
+ - system
+ - unknown
+ description: What initiated this deployment.
+ initiated_by:
+ type: string
+ description: Platform user that triggered a request-initiated deployment; absent for git and system deployments.
+ artifact_bucket:
+ type: string
+ artifact_key:
+ type: string
+ artifact_version:
+ type: string
+ codebuild_duration_seconds:
+ type: integer
+ format: int64
+ description: Total CodeBuild build duration recorded for this deployment, in seconds.
+ codebuild_build_count:
+ type: integer
+ description: Number of completed CodeBuild builds included in codebuild_duration_seconds.
+ codebuild_duration_recorded_at:
+ type: string
+ format: date-time
+ progress:
+ $ref: '#/components/schemas/DeploymentProgress'
+ error_message:
+ type: string
+ completed_at:
+ type: string
+ format: date-time
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - function_id
+ - project_id
+ - operation
+ - status
+ - deploy_source
+ - created_at
+ - updated_at
+ FunctionInvocationRequest:
+ type: object
+ properties:
+ payload:
+ type: object
+ additionalProperties: true
+ description: |
+ Payload to send to the function.
+
+ If invoked with auth user token, Volcano automatically injects `__volcano_auth` context:
+ ```javascript
+ {
+ ...yourPayload,
+ __volcano_auth: {
+ user_id: "uuid",
+ email: "user@example.com",
+ project_id: "uuid",
+ role: "authenticated" | "anonymous"
+ }
+ }
+ ```
+ FunctionInvocationResponse:
+ type: object
+ description: Raw function response body returned by the invoked function.
+ additionalProperties: true
+ LogActivityBucket:
+ type: object
+ description: Log-event counts for one activity time bucket.
+ properties:
+ start_time:
+ type: string
+ format: date-time
+ description: Bucket start time.
+ end_time:
+ type: string
+ format: date-time
+ description: Bucket end time.
+ counts:
+ type: object
+ description: Counts grouped by activity dimension.
+ properties:
+ levels:
+ type: object
+ additionalProperties:
+ type: integer
+ description: Counts by normalized log level.
+ regions:
+ type: object
+ additionalProperties:
+ type: integer
+ description: Counts by event region.
+ resource_ids:
+ type: object
+ additionalProperties:
+ type: integer
+ description: Counts by resource ID.
+ required:
+ - levels
+ - regions
+ - resource_ids
+ total:
+ type: integer
+ description: Total events in this bucket.
+ required:
+ - start_time
+ - end_time
+ - counts
+ - total
+ LogActivityRequest:
+ type: object
+ description: Activity request for bucketed log counts.
+ additionalProperties: false
+ properties:
+ resource:
+ $ref: '#/components/schemas/LogRequestResource'
+ q:
+ type: string
+ maxLength: 512
+ description: Optional activity query. Supports quoted text, implicit AND, AND/OR/NOT, parentheses, and fields such as `level`, `region`, `invocation.id`, `resource.id`, `resource.name`, `function`, `frontend`, `database`, and `body`.
+ start_time:
+ type: string
+ format: date-time
+ description: Start time.
+ end_time:
+ type: string
+ format: date-time
+ description: End time.
+ bucket_count:
+ type: integer
+ minimum: 1
+ maximum: 96
+ description: Number of activity buckets to return.
+ required:
+ - resource
+ LogActivityResponse:
+ type: object
+ description: Bucketed runtime log activity.
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogActivityBucket'
+ total:
+ type: integer
+ description: Total events counted across all buckets.
+ required:
+ - data
+ - total
+ LogSearchRequest:
+ type: object
+ description: Search request for project logs.
+ additionalProperties: false
+ properties:
+ resource:
+ $ref: '#/components/schemas/LogRequestResource'
+ q:
+ type: string
+ maxLength: 512
+ description: Optional log query. Supports quoted text, implicit AND, AND/OR/NOT, parentheses, and fields such as `level`, `region`, `invocation.id`, `resource.id`, `resource.name`, `function`, `frontend`, `database`, and `body`.
+ start_time:
+ type: string
+ format: date-time
+ description: Start time.
+ end_time:
+ type: string
+ format: date-time
+ description: End time.
+ limit:
+ type: integer
+ minimum: 1
+ maximum: 1000
+ default: 100
+ description: Maximum number of records to return.
+ cursor:
+ type: string
+ description: Opaque pagination cursor from the previous response's `next_cursor`.
+ required:
+ - resource
+ LogStreamRequest:
+ type: object
+ description: Stream request for live project logs. Pagination cursors and fixed end times are not supported.
+ additionalProperties: false
+ properties:
+ resource:
+ $ref: '#/components/schemas/LogRequestResource'
+ q:
+ type: string
+ maxLength: 512
+ description: Optional log query using the same syntax as search and activity requests.
+ start_time:
+ type: string
+ format: date-time
+ description: Start time.
+ limit:
+ type: integer
+ minimum: 1
+ maximum: 1000
+ default: 100
+ description: Maximum number of records to deliver on connect or reconnect before following new events.
+ required:
+ - resource
+ LogSearchEvent:
+ allOf:
+ - $ref: '#/components/schemas/LogEvent'
+ - type: object
+ description: Runtime log event returned by project log search. Search results always include a stable event ID and owning resource.
+ properties:
+ id:
+ type: string
+ description: Opaque stable log event ID for pagination, deduplication, and display.
+ resource:
+ $ref: '#/components/schemas/LogResource'
+ required:
+ - id
+ - resource
+ LogSearchResponse:
+ type: object
+ description: Paginated project runtime log search response.
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogSearchEvent'
+ description: Array of log events sorted by timestamp, newest first.
+ limit:
+ type: integer
+ description: Number of items requested per page.
+ has_more:
+ type: boolean
+ description: Whether there are more log events available.
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page. Send this value as `cursor` on the next request.
+ required:
+ - data
+ - limit
+ - has_more
+ FunctionRegion:
+ type: object
+ required:
+ - code
+ - label
+ - flag
+ properties:
+ code:
+ type: string
+ example: us-east-1
+ description: Region identifier accepted by function APIs.
+ label:
+ type: string
+ example: NA-East
+ description: Human-readable region label suitable for display in pickers.
+ flag:
+ type: string
+ example: 🇺🇸
+ description: Country flag emoji associated with the region's geography.
+ FunctionRuntimeOption:
+ type: object
+ required:
+ - name
+ - language
+ - default
+ - deployment
+ properties:
+ name:
+ type: string
+ example: nodejs24.x
+ description: Runtime identifier accepted by function APIs.
+ language:
+ type: string
+ example: nodejs
+ description: Runtime language family used by the CLI to choose defaults from source files.
+ default:
+ type: boolean
+ description: Whether this runtime is the CLI default for its language.
+ deployment:
+ $ref: '#/components/schemas/FunctionRuntimeDeployment'
+ FunctionRuntimesResponse:
+ type: object
+ required:
+ - runtimes
+ properties:
+ runtimes:
+ type: array
+ items:
+ $ref: '#/components/schemas/FunctionRuntimeOption'
+ FunctionScheduler:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ function_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ enabled:
+ type: boolean
+ schedule_kind:
+ type: string
+ enum:
+ - cron
+ cron_expression:
+ type: string
+ payload:
+ type: object
+ additionalProperties: true
+ regions:
+ type: array
+ items:
+ type: string
+ regions_explicit:
+ type: boolean
+ next_run_at:
+ type: string
+ format: date-time
+ last_started_at:
+ type: string
+ format: date-time
+ last_completed_at:
+ type: string
+ format: date-time
+ last_error:
+ type: string
+ run_count:
+ type: integer
+ format: int64
+ description: Total number of times this scheduler has executed. 0 for a scheduler that has never run.
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ FunctionSchedulerListResponse:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/FunctionScheduler'
+ page:
+ type: integer
+ limit:
+ type: integer
+ total:
+ type: integer
+ has_more:
+ type: boolean
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ HostedAuthPageType:
+ type: string
+ enum:
+ - login
+ - reset-password
+ HostedLoginEmailCheckRequest:
+ type: object
+ required:
+ - email
+ properties:
+ email:
+ type: string
+ format: email
+ HostedLoginEmailCheckResponse:
+ type: object
+ properties:
+ exists:
+ type: boolean
+ HostedLoginOptionsResponse:
+ type: object
+ properties:
+ require_email_confirmation:
+ type: boolean
+ email_password_enabled:
+ type: boolean
+ enable_signup:
+ type: boolean
+ post_auth_redirect_url:
+ type: string
+ oauth_providers:
+ type: array
+ items:
+ type: string
+ HostedRenderablePageType:
+ type: string
+ enum:
+ - reset-password
+ LogEvent:
+ type: object
+ description: Historical log event returned by log APIs.
+ properties:
+ id:
+ type: string
+ description: Opaque stable log event ID for pagination, deduplication, and display.
+ timestamp:
+ type: string
+ format: date-time
+ description: Event timestamp.
+ level:
+ $ref: '#/components/schemas/LiveLogLevel'
+ body:
+ description: Application log value. JSON arguments retain their JSON type. Strings containing a serialized JSON object or array are normalized to that object or array; all other strings remain strings.
+ nullable: true
+ oneOf:
+ - type: string
+ - type: object
+ additionalProperties: true
+ - type: array
+ items: {}
+ - type: number
+ format: double
+ - type: boolean
+ region:
+ type: string
+ description: Region where this log event originated.
+ resource:
+ $ref: '#/components/schemas/LogResource'
+ deployment:
+ $ref: '#/components/schemas/LogDeployment'
+ invocation_id:
+ type: string
+ description: Function invocation ID associated with this log event, when available.
+ required:
+ - timestamp
+ - body
+ LiveLogLevel:
+ type: string
+ enum:
+ - trace
+ - debug
+ - info
+ - warn
+ - error
+ - fatal
+ description: Canonical lowercase function runtime log level.
+ MetricUsageData:
+ type: object
+ description: Usage data for one metric across totals, daily, and hourly windows.
+ properties:
+ metric:
+ type: string
+ description: |
+ Metric name (for example, "Function & Frontend Invocations", "Frontend Requests",
+ "CodeBuild Build Seconds", "Bandwidth Ingress (Bytes)", "Bandwidth Egress (Bytes)",
+ "Bandwidth Total (Bytes)", or "Database Storage (Bytes)"). Byte-based metrics are
+ reported in bytes. "Bandwidth Total (Bytes)" is derived (ingress + egress) and
+ is not billed separately. "Database Storage (Bytes)" is a current observed gauge,
+ not a cumulative counter. It is the sum of the latest `pg_database_size` samples
+ exposed as `storage_bytes` by the project's database list.
+ total:
+ type: integer
+ format: int64
+ description: Total usage for the current usage month
+ all_time:
+ type: integer
+ format: int64
+ description: Lifetime cumulative usage across every month for this metric
+ daily:
+ type: array
+ description: Last 30 days of daily usage points
+ items:
+ $ref: '#/components/schemas/UsageDataPoint'
+ hourly:
+ type: array
+ description: Last 24 hours of hourly usage points
+ items:
+ $ref: '#/components/schemas/UsageDataPoint'
+ required:
+ - metric
+ - total
+ - all_time
+ - daily
+ - hourly
+ OAuthConfig:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ provider:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - device
+ client_id:
+ type: string
+ example: 123456789.apps.googleusercontent.com
+ client_secret:
+ type: string
+ description: Masked in responses (shows only first/last 4 chars)
+ example: GOCS...****
+ enabled:
+ type: boolean
+ redirect_url:
+ type: string
+ format: uri
+ example: https://yourapp.com/auth/callback
+ scopes:
+ type: array
+ items:
+ type: string
+ example:
+ - openid
+ - email
+ - profile
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ OAuthErrorResponse:
+ type: object
+ properties:
+ error:
+ type: string
+ error_description:
+ type: string
+ required:
+ - error
+ PaginatedAuthUsers:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/AuthUser'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (only present if has_more is true)
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedDatabases:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Database'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (only present if has_more is true)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedFrontendDeployments:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/FrontendDeployment'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (only present if has_more is true)
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedFrontends:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Frontend'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedFunctionDeployments:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/FunctionDeployment'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (only present if has_more is true)
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedFunctions:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Function'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (only present if has_more is true)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedProjectCustomDomains:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectFrontendCustomDomain'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (only present if has_more is true)
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedProjectDeployments:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectDeployment'
+ page:
+ type: integer
+ minimum: 1
+ description: |
+ Current page number (1-indexed). Offset pagination only — omitted in
+ cursor mode, where position comes from the cursor and there is no page
+ number to report. Required-and-1-indexed would otherwise force a `0`
+ onto every cursor response.
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - limit
+ - total
+ - has_more
+ PaginatedProjects:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Project'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ status:
+ type: string
+ enum:
+ - provisioning
+ - active
+ - failed
+ description: Latest project variable propagation status.
+ current_sync_id:
+ type: string
+ format: uuid
+ description: Identifier of the latest variable propagation sync.
+ provisioning_started_at:
+ type: string
+ format: date-time
+ description: Timestamp when the current variable propagation phase started.
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedServiceKeys:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/ServiceKey'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PaginatedStorageBuckets:
+ type: object
+ description: Cursor-paginated storage buckets (returned only when cursor pagination is requested).
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/StorageBucket'
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items matching the query
+ has_more:
+ type: boolean
+ description: Whether a next page exists
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - limit
+ - has_more
+ PaginatedVariables:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Variable'
+ page:
+ type: integer
+ description: Current page number (1-indexed)
+ limit:
+ type: integer
+ description: Number of items per page
+ total:
+ type: integer
+ description: Total number of items across all pages
+ has_more:
+ type: boolean
+ description: Whether there are more pages available
+ next:
+ type: string
+ description: URL path to next page (only present if has_more is true)
+ next_cursor:
+ type: string
+ description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor:
+ type: string
+ description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
+ required:
+ - data
+ - page
+ - limit
+ - total
+ - has_more
+ PlatformExchangeResponse:
+ type: object
+ properties:
+ token:
+ type: string
+ user_id:
+ type: string
+ token_id:
+ type: string
+ format: uuid
+ expires_at:
+ type: string
+ format: date-time
+ required:
+ - token
+ - user_id
+ - token_id
+ - expires_at
+ Project:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ status:
+ type: string
+ enum:
+ - active
+ - deleting
+ - failed
+ plan:
+ type: string
+ enum:
+ - FREE
+ - PRO
+ description: Platform plan applied to the project when available
+ all_regions:
+ type: boolean
+ description: |
+ Region policy for function deployment.
+ - `true`: deploy functions to all configured platform regions
+ - `false`: deploy only to `selected_regions`
+ selected_regions:
+ type: array
+ items:
+ type: string
+ description: Effective region set for this project (normalized and deduplicated)
+ aws_application_name:
+ type: string
+ last_invoked_at:
+ type: string
+ format: date-time
+ description: Most recent activity timestamp across project resources
+ logo_url:
+ type: string
+ description: |
+ Relative API path that serves the project logo when one has been
+ uploaded. The path is versioned with a `?v=` cache-busting query
+ param that changes on each upload. Absent when the project has no
+ logo. The logo image is stored in the project's storage folder.
+ example: /projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/logo?v=1718524800
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - name
+ - status
+ - all_regions
+ - selected_regions
+ - created_at
+ - updated_at
+ ProjectConfig:
+ type: object
+ additionalProperties: false
+ description: |
+ Declarative project configuration manifest (the JSON form of
+ volcano-config.yaml). Omitted sections are left untouched. Within
+ declared entries, omitted optional fields keep their current server
+ values (patch semantics). Declared collection keys are fully synced to
+ the manifest: `variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, and `functions[].schedulers` are reconciled to
+ exactly match, deleting resources absent from the manifest. Functions,
+ frontends, databases, and buckets are never created or deleted through
+ this manifest; entries referencing resources that do not exist are
+ skipped and reported.
+ properties:
+ version:
+ type: integer
+ enum:
+ - 1
+ description: Manifest schema version. Must be 1.
+ project:
+ $ref: '#/components/schemas/ProjectConfigProject'
+ databases:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigDatabase'
+ variables:
+ type: array
+ description: Fully synced when declared - variables absent from this list are deleted.
+ items:
+ $ref: '#/components/schemas/ProjectConfigVariable'
+ buckets:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigBucket'
+ realtime:
+ $ref: '#/components/schemas/ProjectConfigRealtime'
+ auth:
+ $ref: '#/components/schemas/ProjectConfigAuth'
+ functions:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigFunction'
+ frontends:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigFrontend'
+ required:
+ - version
+ ProjectConfigApplyResult:
+ type: object
+ description: Per-resource report for a project config apply (or dry run).
+ properties:
+ dry_run:
+ type: boolean
+ description: True when the request was a dry run and no changes were made.
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigApplyResultEntry'
+ skipped:
+ type: array
+ description: |
+ Manifest entries referencing functions, frontends, databases, or
+ buckets that do not exist. Their configuration was not applied;
+ deploy/create the resource first, then re-apply.
+ items:
+ $ref: '#/components/schemas/ProjectConfigSkippedResource'
+ missing:
+ type: array
+ description: |
+ Existing functions, frontends, databases, or buckets that have no
+ entry in the corresponding declared manifest section.
+ items:
+ $ref: '#/components/schemas/ProjectConfigMissingResource'
+ summary:
+ $ref: '#/components/schemas/ProjectConfigApplySummary'
+ required:
+ - results
+ - skipped
+ - missing
+ - summary
+ ProjectConfigApplyResultEntry:
+ type: object
+ properties:
+ section:
+ type: string
+ description: Manifest section the entry belongs to (e.g. variables, buckets, auth.providers.oauth).
+ name:
+ type: string
+ description: Resource name or key within the section. Empty for singleton sections.
+ action:
+ type: string
+ enum:
+ - created
+ - updated
+ - deleted
+ - unchanged
+ - error
+ error:
+ type: string
+ description: Error detail when action is `error`.
+ notice:
+ type: string
+ description: Optional operational note (e.g. disabling realtime drops active connections).
+ required:
+ - section
+ - action
+ ProjectConfigApplySummary:
+ type: object
+ properties:
+ created:
+ type: integer
+ updated:
+ type: integer
+ deleted:
+ type: integer
+ unchanged:
+ type: integer
+ errors:
+ type: integer
+ skipped:
+ type: integer
+ missing:
+ type: integer
+ required:
+ - created
+ - updated
+ - deleted
+ - unchanged
+ - errors
+ - skipped
+ - missing
+ ProjectConfigAuth:
+ type: object
+ additionalProperties: false
+ description: Authentication settings, grouped like the dashboard auth-settings tabs.
+ properties:
+ tokens:
+ $ref: '#/components/schemas/ProjectConfigAuthTokens'
+ sessions:
+ $ref: '#/components/schemas/ProjectConfigAuthSessions'
+ signup:
+ $ref: '#/components/schemas/ProjectConfigAuthSignup'
+ rate_limits:
+ $ref: '#/components/schemas/ProjectConfigAuthRateLimits'
+ password:
+ $ref: '#/components/schemas/ProjectConfigAuthPassword'
+ password_reset:
+ $ref: '#/components/schemas/ProjectConfigAuthPasswordReset'
+ email_verification:
+ $ref: '#/components/schemas/ProjectConfigAuthEmailVerification'
+ cors:
+ $ref: '#/components/schemas/ProjectConfigAuthCORS'
+ providers:
+ $ref: '#/components/schemas/ProjectConfigAuthProviders'
+ email:
+ $ref: '#/components/schemas/ProjectConfigAuthEmail'
+ managed_pages:
+ $ref: '#/components/schemas/ProjectConfigAuthManagedPages'
+ ProjectConfigAuthCORS:
+ type: object
+ additionalProperties: false
+ properties:
+ enabled:
+ type: boolean
+ allowed_origins:
+ type: array
+ items:
+ type: string
+ allow_credentials:
+ type: boolean
+ max_age:
+ type: integer
+ ProjectConfigAuthEmail:
+ type: object
+ additionalProperties: false
+ properties:
+ enabled:
+ type: boolean
+ description: Enable transactional email sending
+ from:
+ $ref: '#/components/schemas/ProjectConfigAuthEmailFrom'
+ smtp:
+ $ref: '#/components/schemas/ProjectConfigAuthEmailSMTP'
+ templates:
+ $ref: '#/components/schemas/ProjectConfigEmailTemplates'
+ ProjectConfigAuthEmailFrom:
+ type: object
+ additionalProperties: false
+ properties:
+ address:
+ type: string
+ name:
+ type: string
+ ProjectConfigAuthEmailPasswordProvider:
+ type: object
+ additionalProperties: false
+ properties:
+ enabled:
+ type: boolean
+ ProjectConfigAuthEmailSMTP:
+ type: object
+ additionalProperties: false
+ properties:
+ host:
+ type: string
+ port:
+ type: integer
+ username:
+ type: string
+ password:
+ type: string
+ format: password
+ writeOnly: true
+ description: Write-only; omitted from config export.
+ use_tls:
+ type: boolean
+ ProjectConfigAuthEmailVerification:
+ type: object
+ additionalProperties: false
+ properties:
+ require_confirmation:
+ type: boolean
+ description: Require users to confirm email before sign-in. Requires email sending to be enabled.
+ confirmation_timeout:
+ type: integer
+ description: Email confirmation token expiry in seconds
+ ProjectConfigAuthManagedPages:
+ type: object
+ additionalProperties: false
+ properties:
+ enabled:
+ type: boolean
+ description: Enable or disable managed auth hosted pages
+ redirects:
+ $ref: '#/components/schemas/ProjectConfigAuthRedirects'
+ pages:
+ $ref: '#/components/schemas/ProjectConfigHostedPages'
+ ProjectConfigAuthPassword:
+ type: object
+ additionalProperties: false
+ properties:
+ min_length:
+ type: integer
+ minimum: 15
+ maximum: 128
+ require_uppercase:
+ type: boolean
+ require_lowercase:
+ type: boolean
+ require_numbers:
+ type: boolean
+ require_special_chars:
+ type: boolean
+ ProjectConfigAuthPasswordReset:
+ type: object
+ additionalProperties: false
+ properties:
+ allow:
+ type: boolean
+ timeout:
+ type: integer
+ description: Password reset token expiry in seconds
+ max_history:
+ type: integer
+ description: Number of previous passwords to disallow (0=disabled)
+ ProjectConfigAuthProviders:
+ type: object
+ additionalProperties: false
+ properties:
+ email_password:
+ $ref: '#/components/schemas/ProjectConfigAuthEmailPasswordProvider'
+ oauth:
+ type: array
+ description: Fully synced when declared - providers absent from this list are deleted.
+ items:
+ $ref: '#/components/schemas/ProjectConfigOAuthProvider'
+ ProjectConfigAuthRateLimits:
+ type: object
+ additionalProperties: false
+ description: Rate limits per hour.
+ properties:
+ signup:
+ type: integer
+ signin:
+ type: integer
+ token_refresh:
+ type: integer
+ password_reset:
+ type: integer
+ ProjectConfigAuthRedirects:
+ type: object
+ additionalProperties: false
+ properties:
+ allowed:
+ type: array
+ items:
+ type: string
+ description: Redirect allowlist. Every entry must be a valid http/https URL.
+ post_auth:
+ type: string
+ description: Must be included in `allowed` when set.
+ post_logout:
+ type: string
+ description: Must be included in `allowed` when set.
+ device_verification:
+ type: string
+ description: Optional custom device-authorization verification page URL.
+ ProjectConfigAuthSessions:
+ type: object
+ additionalProperties: false
+ properties:
+ inactivity_timeout:
+ type: integer
+ description: Force re-login after inactivity (seconds, 0=never)
+ max_session_duration:
+ type: integer
+ description: Force re-login after duration (seconds, 0=never)
+ ProjectConfigAuthSignup:
+ type: object
+ additionalProperties: false
+ properties:
+ enable_signup:
+ type: boolean
+ description: Master switch for signups across ALL providers
+ enable_anonymous_signins:
+ type: boolean
+ allowed_email_domains:
+ type: array
+ maxItems: 100
+ description: |
+ Email domains allowed to create users. Empty allows every domain.
+ Replaces the stored list; entries are normalized (lowercase, no `@`
+ prefix) and must be bare domains such as `domain1.com`. Matching is
+ exact, so subdomains need their own entry. At most 100 entries.
+
+ Restricting signups is a PRO feature to configure and to enforce: a
+ FREE project can only declare the list it already has or remove the
+ restriction, and the list it keeps is parked until it upgrades.
+ items:
+ type: string
+ example:
+ - domain1.com
+ - domain2.com
+ allowed_email_domains_mode:
+ type: string
+ description: |
+ How far `allowed_email_domains` reaches. `signup` gates account
+ creation only. `signup_and_signin` also blocks sign-in for accounts
+ outside the list and signs out the ones it locks out. `disabled`
+ keeps the list without enforcing it.
+ enum:
+ - disabled
+ - signup
+ - signup_and_signin
+ ProjectConfigAuthTokens:
+ type: object
+ additionalProperties: false
+ description: Token lifetimes in seconds.
+ properties:
+ access_token_lifetime:
+ type: integer
+ refresh_token_lifetime:
+ type: integer
+ refresh_token_reuse_interval:
+ type: integer
+ platform_token_ttl:
+ type: integer
+ ProjectConfigBucket:
+ type: object
+ additionalProperties: false
+ description: |
+ Settings for an existing storage bucket. Buckets are never created or
+ deleted through the manifest. When `policies` is declared it is fully
+ synced (policies absent from the list are deleted; an empty list
+ deletes all); omitting `policies` leaves the bucket's policies
+ untouched.
+ properties:
+ name:
+ type: string
+ pattern: ^[a-zA-Z0-9_-]+$
+ minLength: 1
+ maxLength: 64
+ file_size_limit:
+ type: integer
+ format: int64
+ description: Maximum file size in bytes
+ allowed_mime_types:
+ type: array
+ items:
+ type: string
+ policies:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigBucketPolicy'
+ required:
+ - name
+ ProjectConfigBucketPolicy:
+ type: object
+ additionalProperties: false
+ properties:
+ name:
+ type: string
+ minLength: 1
+ operation:
+ type: string
+ enum:
+ - SELECT
+ - INSERT
+ - UPDATE
+ - DELETE
+ definition:
+ type: string
+ description: Policy expression
+ required:
+ - name
+ - operation
+ - definition
+ ProjectConfigCustomDomain:
+ type: object
+ additionalProperties: false
+ description: |
+ Custom domain with BYOC TLS (PRO plan). `tls` is required when the
+ domain is first created and optional afterwards: providing new TLS
+ material for the same domain rotates the certificate in place (zero
+ downtime); omitting `tls` keeps the stored certificate. TLS material is
+ write-only and omitted from config export.
+ properties:
+ domain:
+ type: string
+ description: Fully-qualified domain name (hostname only, no scheme/path)
+ tls:
+ $ref: '#/components/schemas/FrontendCustomDomainTLSConfig'
+ required:
+ - domain
+ ProjectConfigDatabase:
+ type: object
+ additionalProperties: false
+ description: |
+ Assertion-only entry for an existing database. No database property is
+ mutable through the manifest; declared values are compared against the
+ deployed database and any mismatch fails validation. Databases are
+ never created or deleted here.
+ properties:
+ name:
+ type: string
+ minLength: 1
+ region:
+ type: string
+ description: Deployed region ID (e.g. aws-us-east-1). Asserted, never written.
+ pg_version:
+ type: string
+ enum:
+ - '15'
+ - '16'
+ description: PostgreSQL major version. Asserted, never written.
+ database_type:
+ type: string
+ enum:
+ - volcano-db-xs
+ - volcano-db-s
+ - volcano-db-m
+ - volcano-db-l
+ - volcano-db-xl
+ - volcano-db-2xl
+ description: |
+ Compute tier. Asserted, never written - tier changes are not
+ supported via the manifest; use the databases API/CLI/GUI instead.
+ required:
+ - name
+ - region
+ - pg_version
+ ProjectConfigEmailTemplate:
+ type: object
+ additionalProperties: false
+ properties:
+ subject:
+ type: string
+ html_body:
+ type: string
+ maxLength: 262144
+ description: HTML body. Max 256 KiB. PRO plan required for custom bodies.
+ text_body:
+ type: string
+ maxLength: 262144
+ description: Plain-text body. Max 256 KiB. PRO plan required for custom bodies.
+ ProjectConfigEmailTemplates:
+ type: object
+ additionalProperties: false
+ description: |
+ Email templates keyed by type. Fully synced when declared - template
+ types absent from a declared map revert to server defaults (custom
+ bodies deleted, subject overrides cleared). Custom template bodies
+ require the PRO plan; subject-only changes are available on FREE.
+ properties:
+ confirmation:
+ $ref: '#/components/schemas/ProjectConfigEmailTemplate'
+ password_reset:
+ $ref: '#/components/schemas/ProjectConfigEmailTemplate'
+ password_changed:
+ $ref: '#/components/schemas/ProjectConfigEmailTemplate'
+ welcome:
+ $ref: '#/components/schemas/ProjectConfigEmailTemplate'
+ ProjectConfigFrontend:
+ type: object
+ additionalProperties: false
+ description: |
+ Configuration for an existing (deployed) frontend. Frontends are never
+ created or deleted through the manifest. A declared frontend entry
+ without `custom_domain` deletes an existing custom domain.
+ properties:
+ name:
+ type: string
+ minLength: 1
+ custom_domain:
+ $ref: '#/components/schemas/ProjectConfigCustomDomain'
+ required:
+ - name
+ ProjectConfigFunction:
+ type: object
+ additionalProperties: false
+ description: |
+ Configuration for an existing (deployed) function. Functions are never
+ created or deleted through the manifest. When `schedulers` is declared
+ it is fully synced (schedulers absent from the list are deleted);
+ omitting `schedulers` leaves the function's schedulers untouched.
+ properties:
+ name:
+ type: string
+ minLength: 1
+ public:
+ type: boolean
+ description: Function visibility for anon-key invocation
+ schedulers:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigScheduler'
+ required:
+ - name
+ ProjectConfigHostedPage:
+ type: object
+ additionalProperties: false
+ properties:
+ html:
+ type: string
+ maxLength: 262144
+ description: Raw HTML markup for the page. Max 256 KiB.
+ css:
+ type: string
+ maxLength: 262144
+ description: Optional CSS injected at render time. Max 256 KiB.
+ required:
+ - html
+ ProjectConfigHostedPages:
+ type: object
+ additionalProperties: false
+ description: |
+ Hosted auth pages keyed by page type (PRO plan). Upsert-only: omitted
+ pages are left untouched (there is no delete for hosted pages).
+ properties:
+ login:
+ $ref: '#/components/schemas/ProjectConfigHostedPage'
+ reset_password:
+ $ref: '#/components/schemas/ProjectConfigHostedPage'
+ ProjectConfigMissingResource:
+ type: object
+ properties:
+ type:
+ type: string
+ enum:
+ - function
+ - frontend
+ - database
+ - bucket
+ name:
+ type: string
+ required:
+ - type
+ - name
+ ProjectConfigOAuthProvider:
+ type: object
+ additionalProperties: false
+ properties:
+ provider:
+ type: string
+ enum:
+ - google
+ - github
+ - microsoft
+ - apple
+ - device
+ enabled:
+ type: boolean
+ client_id:
+ type: string
+ description: |
+ Required for non-device providers. Server-generated for
+ `provider=device` (exported read-only, ignored on apply).
+ client_secret:
+ type: string
+ format: password
+ writeOnly: true
+ description: Write-only; omitted from config export. Not used for `provider=device`.
+ redirect_url:
+ type: string
+ description: Not used for `provider=device`.
+ scopes:
+ type: array
+ items:
+ type: string
+ required:
+ - provider
+ ProjectConfigProject:
+ type: object
+ additionalProperties: false
+ description: Project-level settings. `name` renames the project.
+ properties:
+ name:
+ type: string
+ pattern: ^[A-Za-z0-9_-]+$
+ minLength: 1
+ maxLength: 255
+ all_regions:
+ type: boolean
+ description: Region policy. `false` requires `selected_regions` (PRO plan).
+ selected_regions:
+ type: array
+ items:
+ type: string
+ description: Region subset (bare region names). Requires `all_regions=false`.
+ ProjectConfigRealtime:
+ type: object
+ additionalProperties: false
+ properties:
+ enabled:
+ type: boolean
+ broadcast_enabled:
+ type: boolean
+ presence_enabled:
+ type: boolean
+ postgres_changes_enabled:
+ type: boolean
+ ProjectConfigScheduler:
+ type: object
+ additionalProperties: false
+ properties:
+ name:
+ type: string
+ minLength: 1
+ maxLength: 200
+ cron:
+ type: string
+ description: 5-field UTC cron expression
+ enabled:
+ type: boolean
+ payload:
+ type: object
+ additionalProperties: true
+ required:
+ - name
+ - cron
+ ProjectConfigSkippedResource:
+ type: object
+ properties:
+ type:
+ type: string
+ enum:
+ - function
+ - frontend
+ - database
+ - bucket
+ name:
+ type: string
+ reason:
+ type: string
+ required:
+ - type
+ - name
+ - reason
+ ProjectConfigValidationError:
+ type: object
+ properties:
+ section:
+ type: string
+ description: Manifest section the error refers to (e.g. databases, functions).
+ name:
+ type: string
+ description: Resource name or key within the section, when applicable.
+ message:
+ type: string
+ required:
+ - section
+ - message
+ ProjectConfigValidationErrorResponse:
+ type: object
+ description: Returned when manifest validation fails. Nothing was applied.
+ properties:
+ error:
+ type: string
+ errors:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectConfigValidationError'
+ required:
+ - error
+ - errors
+ ProjectConfigVariable:
+ type: object
+ additionalProperties: false
+ properties:
+ name:
+ type: string
+ minLength: 1
+ value:
+ type: string
+ required:
+ - name
+ - value
+ ProjectHealthResource:
+ type: object
+ properties:
+ type:
+ type: string
+ enum:
+ - project
+ - function
+ - frontend
+ - database
+ id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ required:
+ - type
+ - id
+ - name
+ ResourceReference:
+ type: object
+ description: Stable reference to a Volcano resource.
+ properties:
+ type:
+ type: string
+ enum:
+ - project
+ - function
+ - frontend
+ - database
+ id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ required:
+ - type
+ - id
+ - name
+ DeploymentReference:
+ type: object
+ description: Stable reference to a Volcano deployment run.
+ properties:
+ id:
+ type: string
+ format: uuid
+ required:
+ - id
+ ProjectHealthScope:
+ type: object
+ properties:
+ resource:
+ $ref: '#/components/schemas/ProjectHealthResource'
+ required:
+ - resource
+ ProjectHealthResponse:
+ type: object
+ properties:
+ project_id:
+ type: string
+ format: uuid
+ status:
+ $ref: '#/components/schemas/ProjectHealthStatus'
+ observed_at:
+ type: string
+ format: date-time
+ fresh_through:
+ type: string
+ format: date-time
+ data_status:
+ $ref: '#/components/schemas/ProjectHealthDataStatus'
+ checks:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectHealthCheck'
+ findings:
+ description: Top findings ordered by severity, then stable check ID.
+ type: array
+ maxItems: 5
+ items:
+ $ref: '#/components/schemas/ProjectHealthCheck'
+ required:
+ - project_id
+ - status
+ - observed_at
+ - fresh_through
+ - data_status
+ - checks
+ - findings
+ ProjectHealthStatus:
+ type: string
+ enum:
+ - healthy
+ - degraded
+ - critical
+ - unknown
+ ProjectHealthDataStatus:
+ type: string
+ enum:
+ - complete
+ - partial
+ - no_data
+ - stale
+ ProjectHealthCategory:
+ type: string
+ enum:
+ - lifecycle
+ - storage
+ ProjectHealthEvidence:
+ type: object
+ properties:
+ metric:
+ type: string
+ value:
+ type: number
+ format: double
+ unit:
+ type: string
+ sample_count:
+ type: integer
+ format: int64
+ minimum: 0
+ required:
+ - metric
+ - value
+ - unit
+ - sample_count
+ ProjectHealthCheck:
+ type: object
+ properties:
+ id:
+ type: string
+ category:
+ $ref: '#/components/schemas/ProjectHealthCategory'
+ status:
+ $ref: '#/components/schemas/ProjectHealthStatus'
+ reason_code:
+ type: string
+ scope:
+ $ref: '#/components/schemas/ProjectHealthScope'
+ evidence:
+ $ref: '#/components/schemas/ProjectHealthEvidence'
+ required:
+ - id
+ - category
+ - status
+ - reason_code
+ - scope
+ - evidence
+ ProjectMetricsDataStatus:
+ type: string
+ enum:
+ - complete
+ - partial
+ - no_data
+ ProjectMetricsDimensions:
+ type: object
+ additionalProperties: false
+ properties:
+ region:
+ type: string
+ resource_type:
+ type: string
+ enum:
+ - function
+ - frontend
+ ProjectMetricsGroupBy:
+ type: string
+ enum:
+ - region
+ - resource_type
+ ProjectMetricsMetric:
+ type: string
+ enum:
+ - request_count
+ - server_error_count
+ - availability
+ - p95_latency
+ ProjectMetricsQuery:
+ type: object
+ additionalProperties: false
+ properties:
+ id:
+ type: string
+ minLength: 1
+ maxLength: 64
+ pattern: ^[A-Za-z][A-Za-z0-9_-]*$
+ metric:
+ $ref: '#/components/schemas/ProjectMetricsMetric'
+ group_by:
+ $ref: '#/components/schemas/ProjectMetricsGroupBy'
+ required:
+ - id
+ - metric
+ ProjectMetricsQueryRequest:
+ type: object
+ additionalProperties: false
+ properties:
+ time_range:
+ $ref: '#/components/schemas/ProjectMetricsQueryTimeRange'
+ queries:
+ type: array
+ minItems: 1
+ maxItems: 10
+ items:
+ $ref: '#/components/schemas/ProjectMetricsQuery'
+ required:
+ - time_range
+ - queries
+ ProjectMetricsQueryResponse:
+ type: object
+ additionalProperties: false
+ properties:
+ observed_at:
+ type: string
+ format: date-time
+ fresh_through:
+ type: string
+ format: date-time
+ window:
+ $ref: '#/components/schemas/ProjectMetricsWindow'
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectMetricsResult'
+ required:
+ - observed_at
+ - window
+ - results
+ ProjectMetricsQueryTimeRange:
+ type: object
+ additionalProperties: false
+ properties:
+ window:
+ type: string
+ enum:
+ - 30m
+ - 1h
+ - 24h
+ - 7d
+ required:
+ - window
+ ProjectMetricsResult:
+ type: object
+ additionalProperties: false
+ properties:
+ id:
+ type: string
+ metric:
+ $ref: '#/components/schemas/ProjectMetricsMetric'
+ unit:
+ $ref: '#/components/schemas/ProjectMetricsUnit'
+ data_status:
+ $ref: '#/components/schemas/ProjectMetricsDataStatus'
+ values:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectMetricsValue'
+ required:
+ - id
+ - metric
+ - unit
+ - data_status
+ - values
+ ProjectMetricsUnit:
+ type: string
+ enum:
+ - count
+ - ratio
+ - seconds
+ ProjectMetricsValue:
+ type: object
+ additionalProperties: false
+ properties:
+ dimensions:
+ $ref: '#/components/schemas/ProjectMetricsDimensions'
+ value:
+ type: number
+ format: double
+ minimum: 0
+ required:
+ - dimensions
+ - value
+ ProjectMetricsWindow:
+ type: object
+ properties:
+ from:
+ type: string
+ format: date-time
+ to:
+ type: string
+ format: date-time
+ required:
+ - from
+ - to
+ ProjectFrontendCustomDomain:
+ allOf:
+ - $ref: '#/components/schemas/FrontendCustomDomainResponse'
+ - type: object
+ properties:
+ frontend:
+ type: object
+ description: |
+ The frontend this custom domain is attached to. Inlined to
+ avoid a second fetch from the project-scoped feed.
+ properties:
+ id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ required:
+ - id
+ - name
+ required:
+ - frontend
+ ProjectDeployment:
+ type: object
+ description: A Function or Frontend deployment attempt in a project-scoped feed.
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ resource:
+ $ref: '#/components/schemas/ProjectDeploymentResource'
+ operation:
+ type: string
+ enum:
+ - deploy
+ - redeploy
+ - update
+ - delete
+ status:
+ type: string
+ enum:
+ - queued
+ - provisioning
+ - active
+ - degraded
+ - failed
+ - superseded
+ - deleting
+ - deleted
+ deploy_source:
+ type: string
+ enum:
+ - git
+ - cli
+ - web
+ - api
+ - system
+ - unknown
+ description: What initiated this deployment.
+ artifact_version:
+ type: string
+ error_message:
+ type: string
+ completed_at:
+ type: string
+ format: date-time
+ progress:
+ $ref: '#/components/schemas/DeploymentProgress'
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - project_id
+ - resource
+ - operation
+ - status
+ - deploy_source
+ - created_at
+ - updated_at
+ ProjectDeploymentResource:
+ type: object
+ description: The resource this deployment belongs to.
+ properties:
+ type:
+ type: string
+ enum:
+ - function
+ - frontend
+ id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ required:
+ - type
+ - id
+ - name
+ ProjectDeploymentSummary:
+ type: object
+ description: Aggregate deployment statistics for one resource pipeline.
+ properties:
+ deployment_count:
+ type: integer
+ description: All deployment attempts matching the filters.
+ successful_count:
+ type: integer
+ description: Attempts that reached active or deleted.
+ failed_count:
+ type: integer
+ description: Attempts that reached failed or degraded.
+ canceled_count:
+ type: integer
+ description: Superseded attempts, excluded from success rate and duration.
+ success_rate:
+ type: number
+ format: double
+ minimum: 0
+ maximum: 1
+ nullable: true
+ description: Successful attempts divided by successful plus failed attempts.
+ median_build_duration_seconds:
+ type: number
+ format: double
+ minimum: 0
+ nullable: true
+ description: Median CodeBuild duration across eligible completed attempts.
+ required:
+ - deployment_count
+ - successful_count
+ - failed_count
+ - canceled_count
+ - success_rate
+ - median_build_duration_seconds
+ ProjectUsageResponse:
+ type: object
+ description: Aggregated usage metrics for a project.
+ properties:
+ project_id:
+ type: string
+ format: uuid
+ description: Project ID
+ month:
+ type: string
+ description: Usage month in YYYY-MM format
+ example: 2026-02
+ metrics:
+ type: array
+ description: Usage metrics for the project
+ items:
+ $ref: '#/components/schemas/MetricUsageData'
+ frontends:
+ type: array
+ description: Per-frontend request totals for the current usage month
+ items:
+ $ref: '#/components/schemas/FrontendUsageData'
+ required:
+ - project_id
+ - month
+ - metrics
+ RealtimeConfig:
+ type: object
+ description: |
+ Realtime configuration for a project.
+ Note: Message size and channels per connection are plan-based (not configurable).
+ properties:
+ project_id:
+ type: string
+ format: uuid
+ description: Project ID
+ enabled:
+ type: boolean
+ description: Whether realtime is enabled for this project
+ default: false
+ broadcast_enabled:
+ type: boolean
+ description: Whether broadcast channels are enabled
+ default: true
+ presence_enabled:
+ type: boolean
+ description: Whether presence tracking is enabled
+ default: true
+ postgres_changes_enabled:
+ type: boolean
+ description: Whether Postgres change notifications are enabled
+ default: true
+ created_at:
+ type: string
+ format: date-time
+ description: When the configuration was created
+ updated_at:
+ type: string
+ format: date-time
+ description: When the configuration was last updated
+ RealtimePlanLimits:
+ type: object
+ description: Plan-based limits for realtime features
+ properties:
+ plan:
+ type: string
+ description: Plan name (FREE or PRO)
+ example: FREE
+ max_connections:
+ type: integer
+ description: Maximum concurrent connections allowed
+ example: 100
+ messages_per_month:
+ type: integer
+ description: Maximum messages per month
+ example: 1000000
+ message_size_kb:
+ type: integer
+ description: Maximum message size in KB
+ example: 32
+ channels_per_conn:
+ type: integer
+ description: Maximum channels per connection
+ example: 100
+ RealtimeStats:
+ type: object
+ description: Realtime usage statistics for a project
+ properties:
+ num_connections:
+ type: integer
+ description: Current number of active connections
+ peak_connections:
+ type: integer
+ description: Peak concurrent connections this usage period
+ last_invoked_at:
+ type: string
+ format: date-time
+ description: Most recent realtime activity timestamp across channels
+ limits:
+ $ref: '#/components/schemas/RealtimePlanLimits'
+ ResolveFunctionResponse:
+ type: object
+ properties:
+ name:
+ type: string
+ maxLength: 63
+ pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
+ description: DNS-safe function name
+ function_id:
+ type: string
+ format: uuid
+ description: Canonical function ID used for invocation routing
+ cache_ttl_seconds:
+ type: integer
+ minimum: 1
+ description: Suggested SDK cache TTL for this name-to-ID mapping
+ required:
+ - name
+ - function_id
+ - cache_ttl_seconds
+ ScheduleRequest:
+ type: object
+ required:
+ - cron_expression
+ properties:
+ kind:
+ type: string
+ enum:
+ - cron
+ default: cron
+ cron_expression:
+ type: string
+ description: Standard 5-field cron expression evaluated in UTC. Seconds fields, descriptors, and Quartz syntax are not supported.
+ example: '*/5 * * * *'
+ ServiceKey:
+ type: object
+ description: |
+ Service role key for admin operations.
+ **WARNING:** Bypasses all RLS - backend use only!
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ description: Descriptive name for the key
+ key_value:
+ type: string
+ description: |
+ Full JWT token for Authorization header.
+ Returned on create, get, and list (decrypted from storage).
+ **Store securely - NEVER expose in frontend code!**
+ key_prefix:
+ type: string
+ description: First 12 characters of the key for display/identification
+ maxLength: 12
+ permissions:
+ type: array
+ items:
+ type: string
+ description: |
+ Operations this key may perform. ["*"] grants full admin access
+ (default for keys created without an explicit scope). Scoped keys
+ list specific permissions, e.g. ["functions.invoke", "locks.manage"].
+ example:
+ - '*'
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - name
+ - key_prefix
+ - permissions
+ StorageBucket:
+ type: object
+ description: |
+ A named container for files within a project.
+ Public access is controlled at the file level via is_public on StorageObject.
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ description: Bucket name (unique within project)
+ pattern: ^[a-zA-Z0-9_-]+$
+ minLength: 1
+ maxLength: 64
+ file_size_limit:
+ type: integer
+ format: int64
+ nullable: true
+ description: Maximum file size in bytes (null for no limit)
+ allowed_mime_types:
+ type: array
+ nullable: true
+ items:
+ type: string
+ description: Allowed MIME types (null for all types)
+ last_invoked_at:
+ type: string
+ format: date-time
+ description: Most recent bucket operation timestamp
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - name
+ StorageCopyRequest:
+ type: object
+ properties:
+ from:
+ type: string
+ description: Source path
+ to:
+ type: string
+ description: Destination path
+ required:
+ - from
+ - to
+ StorageListResponse:
+ type: object
+ properties:
+ objects:
+ type: array
+ items:
+ $ref: '#/components/schemas/StorageObject'
+ next_cursor:
+ type: string
+ description: Cursor for next page (empty if no more results)
+ StorageMoveRequest:
+ type: object
+ properties:
+ from:
+ type: string
+ description: Source path
+ to:
+ type: string
+ description: Destination path
+ required:
+ - from
+ - to
+ StorageObject:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ bucket_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ description: Full path within bucket (e.g., "users/abc123/avatar.png")
+ owner_id:
+ type: string
+ format: uuid
+ nullable: true
+ description: Auth user who uploaded (null for anonymous/service)
+ is_public:
+ type: boolean
+ default: false
+ description: |
+ If true, the file can be downloaded with just an anon key (no user authentication).
+ Files are private by default. Only the owner or a service key can change visibility.
+ size:
+ type: integer
+ format: int64
+ description: File size in bytes
+ mime_type:
+ type: string
+ description: MIME type
+ etag:
+ type: string
+ description: Entity tag for cache validation
+ metadata:
+ type: object
+ additionalProperties: true
+ description: |
+ Custom user metadata (key-value pairs).
+ Limits: Maximum 50 keys, maximum 10KB total serialized size.
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ public_url:
+ type: string
+ format: uri
+ description: |
+ Shareable public URL for this file (only set for public files with is_public=true).
+ This URL requires NO authentication and can be embedded in HTML, shared via email, etc.
+ The URL is properly URL-encoded by the server - use it as-is without additional encoding.
+ required:
+ - id
+ - bucket_id
+ - name
+ - is_public
+ - size
+ - mime_type
+ StorageObjectWithBucket:
+ type: object
+ description: Storage object with bucket name included (for admin listing across buckets)
+ properties:
+ id:
+ type: string
+ format: uuid
+ bucket_id:
+ type: string
+ format: uuid
+ bucket_name:
+ type: string
+ description: Name of the bucket containing this object
+ name:
+ type: string
+ description: Full path within bucket
+ owner_id:
+ type: string
+ format: uuid
+ nullable: true
+ description: Auth user who uploaded (null for anonymous/service)
+ is_public:
+ type: boolean
+ default: false
+ size:
+ type: integer
+ format: int64
+ description: File size in bytes
+ mime_type:
+ type: string
+ etag:
+ type: string
+ metadata:
+ type: object
+ additionalProperties: true
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ public_url:
+ type: string
+ format: uri
+ description: |
+ Shareable public URL for this file (only set for public files with is_public=true).
+ This URL requires NO authentication and can be embedded in HTML, shared via email, etc.
+ required:
+ - id
+ - bucket_id
+ - bucket_name
+ - name
+ - is_public
+ - size
+ - mime_type
+ StoragePolicy:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ bucket_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ description: Policy name (unique within bucket)
+ operation:
+ type: string
+ enum:
+ - SELECT
+ - INSERT
+ - UPDATE
+ - DELETE
+ description: Operation this policy applies to
+ definition:
+ type: string
+ description: |
+ Policy expression evaluated at request time.
+ Examples:
+ - "true" - Allow all
+ - "auth.uid() = owner_id" - Owner only
+ - "auth.role() = 'authenticated'" - Authenticated users
+ - "(storage.foldername(name))[1] = auth.uid()::text" - User's folder
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - bucket_id
+ - name
+ - operation
+ - definition
+ StorageStats:
+ type: object
+ description: Aggregate storage statistics for a project
+ properties:
+ bucket_count:
+ type: integer
+ description: Number of storage buckets
+ object_count:
+ type: integer
+ description: Total number of stored files
+ total_size:
+ type: integer
+ format: int64
+ description: Total storage used in bytes
+ required:
+ - bucket_count
+ - object_count
+ - total_size
+ StorageVisibilityRequest:
+ type: object
+ properties:
+ is_public:
+ type: boolean
+ description: Whether the file should be publicly accessible
+ required:
+ - is_public
+ UnbanUserResponse:
+ type: object
+ description: Response when unbanning a user
+ properties:
+ message:
+ type: string
+ example: User unbanned successfully
+ user_id:
+ type: string
+ format: uuid
+ email:
+ type: string
+ format: email
+ status:
+ type: string
+ enum:
+ - active
+ required:
+ - message
+ - user_id
+ - email
+ - status
+ TestEmailRequest:
+ type: object
+ required:
+ - to_email
+ description: |
+ When `html_body` or `text_body` is provided the backend renders
+ those (plus optional `subject`) through html/text templates
+ against the standard `Data` (ProjectName, Name, SiteURL)
+ and sends the result — used by the template-editor "Send Test"
+ affordance to preview an unsaved template. When both bodies are
+ omitted a hardcoded diagnostic message is sent to verify SMTP
+ credentials and `subject` is ignored. Sending `subject` alone
+ (without a body) is rejected with 400.
+ properties:
+ to_email:
+ type: string
+ format: email
+ description: Recipient address for the diagnostic email.
+ subject:
+ type: string
+ description: |
+ Optional subject override, rendered as a text/template. Only
+ applied on the override path — requires `html_body` or
+ `text_body` to also be set, otherwise the request is
+ rejected with 400.
+ html_body:
+ type: string
+ maxLength: 262144
+ description: Optional HTML body override. Rendered as an html/template. Max 256 KiB.
+ text_body:
+ type: string
+ maxLength: 262144
+ description: Optional plain-text body override. Rendered as a text/template. Max 256 KiB.
+ TestEmailResponse:
+ type: object
+ required:
+ - success
+ properties:
+ success:
+ type: boolean
+ UpdateAuthConfigRequest:
+ type: object
+ description: 'All fields optional - only include fields you want to update. Validation rule: require_email_confirmation=true requires email_enabled=true.'
+ properties:
+ access_token_lifetime:
+ type: integer
+ refresh_token_lifetime:
+ type: integer
+ inactivity_timeout:
+ type: integer
+ max_session_duration:
+ type: integer
+ min_password_length:
+ type: integer
+ minimum: 15
+ maximum: 128
+ require_uppercase:
+ type: boolean
+ require_lowercase:
+ type: boolean
+ require_numbers:
+ type: boolean
+ require_special_chars:
+ type: boolean
+ enable_signup:
+ type: boolean
+ description: Master switch for signups across ALL providers
+ enable_email_password:
+ type: boolean
+ description: Enable/disable email/password provider
+ rate_limit_signup:
+ type: integer
+ rate_limit_signin:
+ type: integer
+ rate_limit_token_refresh:
+ type: integer
+ cors_allow_credentials:
+ type: boolean
+ cors_max_age:
+ type: integer
+ enable_anonymous_signins:
+ type: boolean
+ allowed_email_domains:
+ type: array
+ maxItems: 100
+ description: |
+ Replaces the email domain allowlist. Empty array removes the
+ restriction so any domain can sign up. Entries must be bare domains
+ such as `domain1.com` and are stored normalized (lowercase, no `@`
+ prefix); matching is exact, so subdomains need their own entry. At
+ most 100 entries.
+
+ Restricting signups is a PRO feature to configure and to enforce: a
+ FREE project can only remove the restriction and gets 403 for any
+ other change, and the list it keeps is parked until it upgrades.
+ items:
+ type: string
+ example:
+ - domain1.com
+ - domain2.com
+ allowed_email_domains_mode:
+ type: string
+ description: |
+ How far `allowed_email_domains` reaches. `signup` gates account
+ creation only. `signup_and_signin` also blocks sign-in for accounts
+ outside the list; switching to it, or narrowing the list while in
+ it, deletes the sessions of every account it locks out. `disabled`
+ keeps the list without enforcing it.
+ enum:
+ - disabled
+ - signup
+ - signup_and_signin
+ allow_password_reset:
+ type: boolean
+ password_reset_timeout:
+ type: integer
+ max_password_history:
+ type: integer
+ require_email_confirmation:
+ type: boolean
+ description: Require users to confirm email before sign-in. Can only be true when email_enabled is true.
+ email_confirmation_timeout:
+ type: integer
+ description: Email confirmation token expiry in seconds.
+ auto_link_verified_oauth:
+ type: boolean
+ description: Link a verified OAuth identity to an existing confirmed account with the same email instead of returning a conflict. Requires require_email_confirmation to be true.
+ email_enabled:
+ type: boolean
+ description: Enable transactional email sending. Cannot be false while require_email_confirmation is true.
+ email_from_address:
+ type: string
+ email_from_name:
+ type: string
+ smtp_host:
+ type: string
+ smtp_port:
+ type: integer
+ smtp_username:
+ type: string
+ smtp_password:
+ type: string
+ format: password
+ writeOnly: true
+ minLength: 1
+ description: Replacement SMTP password. Omit this field to preserve the configured password. The value is encrypted at rest and never returned.
+ smtp_use_tls:
+ type: boolean
+ email_confirmation_subject:
+ type: string
+ email_password_reset_subject:
+ type: string
+ email_password_changed_subject:
+ type: string
+ managed_auth_enabled:
+ type: boolean
+ description: Enable or disable managed auth hosted pages for the project.
+ post_auth_redirect_url:
+ type: string
+ description: Must be included in allowed_redirect_urls when set.
+ allowed_redirect_urls:
+ type: array
+ items:
+ type: string
+ description: Redirect allowlist. Every entry must be a valid http/https URL.
+ post_logout_redirect_url:
+ type: string
+ description: Must be included in allowed_redirect_urls when set.
+ device_verification_url:
+ type: string
+ description: |
+ Optional custom device-authorization verification page. Must be a
+ valid http/https URL (not tied to allowed_redirect_urls). When set,
+ device-code logins return this URL (with user_code) instead of the
+ managed device page. Send an empty string to clear the override.
+ UpdateAuthHostedPageRequest:
+ type: object
+ required:
+ - html
+ properties:
+ html:
+ type: string
+ description: Raw HTML markup for the page. Max 256 KiB.
+ css:
+ type: string
+ description: Optional CSS injected at render time. Max 256 KiB.
+ UpdateDatabaseTypeRequest:
+ type: object
+ description: Update database compute size tier
+ properties:
+ database_type:
+ type: string
+ description: New compute size tier
+ enum:
+ - volcano-db-xs
+ - volcano-db-s
+ - volcano-db-m
+ - volcano-db-l
+ - volcano-db-xl
+ - volcano-db-2xl
+ example: volcano-db-m
+ required:
+ - database_type
+ UpdateEmailTemplateRequest:
+ type: object
+ properties:
+ subject:
+ type: string
+ html_body:
+ type: string
+ text_body:
+ type: string
+ UpdateFunctionRequest:
+ type: object
+ properties:
+ is_public:
+ type: boolean
+ description: |
+ Function visibility for anon-key invocation.
+ - `false` (default): private function
+ - `true`: public function (anon keys with `functions.invoke` can invoke)
+ required:
+ - is_public
+ UpdateFunctionSchedulerRequest:
+ type: object
+ properties:
+ name:
+ type: string
+ maxLength: 200
+ enabled:
+ type: boolean
+ schedule:
+ $ref: '#/components/schemas/ScheduleRequest'
+ payload:
+ type: object
+ additionalProperties: true
+ regions:
+ type: array
+ maxItems: 1
+ items:
+ type: string
+ UpdateOAuthConfigRequest:
+ type: object
+ properties:
+ client_id:
+ type: string
+ description: Supported for non-device providers. Not supported for `provider=device`.
+ client_secret:
+ type: string
+ description: Supported for non-device providers. Not supported for `provider=device`.
+ redirect_url:
+ type: string
+ format: uri
+ scopes:
+ type: array
+ items:
+ type: string
+ enabled:
+ type: boolean
+ UpdateProjectRequest:
+ type: object
+ description: Update mutable project fields (name and/or region policy)
+ properties:
+ name:
+ type: string
+ minLength: 1
+ maxLength: 255
+ example: my-awesome-app-renamed
+ all_regions:
+ type: boolean
+ description: |
+ If omitted and `selected_regions` is also omitted, existing region policy is preserved.
+ If `selected_regions` is provided without `all_regions`, it is treated as subset mode.
+ selected_regions:
+ type: array
+ items:
+ type: string
+ description: |
+ Region subset for project deployments.
+ Provide with `all_regions=false`.
+ example:
+ - us-east-1
+ UpdateRealtimeConfigRequest:
+ type: object
+ description: |
+ Request to update realtime configuration.
+ Limits (message size, channels per connection) are plan-based and cannot be configured.
+ properties:
+ enabled:
+ type: boolean
+ description: Whether realtime is enabled for this project
+ broadcast_enabled:
+ type: boolean
+ description: Whether broadcast channels are enabled
+ presence_enabled:
+ type: boolean
+ description: Whether presence tracking is enabled
+ postgres_changes_enabled:
+ type: boolean
+ description: Whether Postgres change notifications are enabled
+ UpdateStorageBucketRequest:
+ type: object
+ properties:
+ file_size_limit:
+ type: integer
+ format: int64
+ allowed_mime_types:
+ type: array
+ items:
+ type: string
+ UpdateVariableRequest:
+ type: object
+ properties:
+ value:
+ type: string
+ required:
+ - value
+ UploadSessionPart:
+ type: object
+ description: Information about an uploaded part
+ properties:
+ part_number:
+ type: integer
+ description: Part number (1-10000)
+ etag:
+ type: string
+ description: ETag of the uploaded part
+ size:
+ type: integer
+ format: int64
+ description: Size of the part in bytes
+ UploadSessionStatusResponse:
+ type: object
+ description: Status of an upload session
+ properties:
+ session_id:
+ type: string
+ description: Upload session ID
+ status:
+ type: string
+ enum:
+ - pending
+ - uploading
+ - completing
+ - completed
+ - aborted
+ description: Current status of the upload
+ path:
+ type: string
+ description: Target file path
+ content_type:
+ type: string
+ description: MIME type
+ total_size:
+ type: integer
+ format: int64
+ description: Total file size in bytes
+ part_size:
+ type: integer
+ format: int64
+ description: Size of each part (except last)
+ total_parts:
+ type: integer
+ description: Total number of parts
+ parts_uploaded:
+ type: integer
+ description: Number of parts uploaded
+ bytes_uploaded:
+ type: integer
+ format: int64
+ description: Total bytes uploaded so far
+ parts:
+ type: array
+ description: List of uploaded parts (for resume)
+ items:
+ $ref: '#/components/schemas/UploadSessionPart'
+ expires_at:
+ type: string
+ format: date-time
+ description: Session expiry time
+ created_at:
+ type: string
+ format: date-time
+ description: Session creation time
+ UsageDataPoint:
+ type: object
+ description: A single timestamped usage value.
+ properties:
+ timestamp:
+ type: string
+ format: date-time
+ description: UTC timestamp for the data point
+ value:
+ type: integer
+ format: int64
+ description: Usage value at the timestamp
+ required:
+ - timestamp
+ - value
+ Variable:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ project_id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ maxLength: 256
+ value:
+ type: string
+ status:
+ type: string
+ enum:
+ - provisioning
+ - active
+ - failed
+ description: Latest project variable propagation status, when a sync has run.
+ current_sync_id:
+ type: string
+ format: uuid
+ description: Identifier of the latest variable propagation sync.
+ provisioning_started_at:
+ type: string
+ format: date-time
+ description: Timestamp when the current variable propagation phase started.
+ deploy_source:
+ type: string
+ enum:
+ - git
+ - cli
+ - web
+ - api
+ - system
+ - unknown
+ description: What initiated the latest variable propagation sync, when one has run.
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - id
+ - project_id
+ - name
+ - value
+ - created_at
+ - updated_at
+ DatabaseQueryPerformanceDatabase:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ name:
+ type: string
+ required:
+ - id
+ - name
+ DatabaseQueryPerformanceItem:
+ type: object
+ properties:
+ query_id:
+ type: string
+ description: pg_stat_statements query identifier.
+ query:
+ type: string
+ maxLength: 8192
+ description: Normalized and obfuscated representative query text.
+ database:
+ $ref: '#/components/schemas/DatabaseQueryPerformanceDatabase'
+ role:
+ type: string
+ description: Database role used for the query.
+ calls:
+ type: integer
+ format: int64
+ total_exec_time_seconds:
+ type: number
+ format: double
+ description: Cumulative total execution time from pg_stat_statements in seconds.
+ max_exec_time_seconds:
+ type: number
+ format: double
+ mean_exec_time_seconds:
+ type: number
+ format: double
+ min_exec_time_seconds:
+ type: number
+ format: double
+ rows_processed:
+ type: integer
+ format: int64
+ required:
+ - query_id
+ - query
+ - database
+ - role
+ - calls
+ - total_exec_time_seconds
+ - max_exec_time_seconds
+ - mean_exec_time_seconds
+ - min_exec_time_seconds
+ - rows_processed
+ DeploymentPhase:
+ type: object
+ description: Timing and outcome for one normalized deployment pipeline phase.
+ properties:
+ name:
+ type: string
+ enum:
+ - queue
+ - checkout
+ - build
+ - image
+ - provisioning
+ - rollout
+ - verification
+ status:
+ type: string
+ enum:
+ - pending
+ - in_progress
+ - succeeded
+ - failed
+ - skipped
+ started_at:
+ type: string
+ format: date-time
+ completed_at:
+ type: string
+ format: date-time
+ duration_seconds:
+ type: integer
+ format: int64
+ minimum: 0
+ required:
+ - name
+ - status
+ DeploymentProgress:
+ type: object
+ description: Normalized live progress derived from the deployment workflow and build phases.
+ properties:
+ current_phase:
+ type: string
+ enum:
+ - queue
+ - checkout
+ - build
+ - image
+ - provisioning
+ - rollout
+ - verification
+ started_at:
+ type: string
+ format: date-time
+ completed_at:
+ type: string
+ format: date-time
+ elapsed_seconds:
+ type: integer
+ format: int64
+ minimum: 0
+ phases:
+ type: array
+ minItems: 7
+ maxItems: 7
+ items:
+ $ref: '#/components/schemas/DeploymentPhase'
+ updated_at:
+ type: string
+ format: date-time
+ required:
+ - started_at
+ - elapsed_seconds
+ - phases
+ - updated_at
+ LogDeploymentRequestSelector:
+ type: object
+ description: Deployment log selector for deployable resources.
+ additionalProperties: false
+ properties:
+ ids:
+ type: array
+ maxItems: 25
+ description: Optional deployment identifiers. Omit or send an empty array to include every deployment for the selected resources.
+ items:
+ type: string
+ format: uuid
+ LogFunctionRequestResource:
+ type: object
+ description: Edge Function log resource selector.
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - function
+ description: Resource type to read logs for.
+ ids:
+ type: array
+ maxItems: 25
+ description: Optional function identifiers. Omit or send an empty array to include every function in the project.
+ items:
+ type: string
+ format: uuid
+ deployments:
+ $ref: '#/components/schemas/LogDeploymentRequestSelector'
+ required:
+ - type
+ LogFrontendRequestResource:
+ type: object
+ description: Frontend log resource selector.
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - frontend
+ description: Resource type to read logs for.
+ ids:
+ type: array
+ maxItems: 25
+ description: Optional frontend identifiers. Omit or send an empty array to include every frontend in the project.
+ items:
+ type: string
+ format: uuid
+ deployments:
+ $ref: '#/components/schemas/LogDeploymentRequestSelector'
+ required:
+ - type
+ LogDatabaseRequestResource:
+ type: object
+ description: Database runtime log resource selector. Deployment logs are not supported for databases.
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - database
+ description: Resource type to read logs for.
+ ids:
+ type: array
+ maxItems: 25
+ description: Optional database identifiers. Omit or send an empty array to include every database in the project.
+ items:
+ type: string
+ format: uuid
+ required:
+ - type
+ LogRequestResource:
+ description: Resource selectors for project log reads.
+ oneOf:
+ - $ref: '#/components/schemas/LogFunctionRequestResource'
+ - $ref: '#/components/schemas/LogFrontendRequestResource'
+ - $ref: '#/components/schemas/LogDatabaseRequestResource'
+ discriminator:
+ propertyName: type
+ mapping:
+ function: '#/components/schemas/LogFunctionRequestResource'
+ frontend: '#/components/schemas/LogFrontendRequestResource'
+ database: '#/components/schemas/LogDatabaseRequestResource'
+ LogResource:
+ type: object
+ description: Resource that owns a historical log event.
+ properties:
+ type:
+ type: string
+ enum:
+ - function
+ - frontend
+ - database
+ description: Resource type that owns the log event.
+ id:
+ type: string
+ format: uuid
+ description: Resource ID that owns the log event.
+ name:
+ type: string
+ description: Resource name associated with the log event, when available.
+ required:
+ - type
+ - id
+ LogDeployment:
+ type: object
+ description: Deployment context associated with a historical deployment log event.
+ properties:
+ id:
+ type: string
+ format: uuid
+ description: Deployment ID associated with the log event.
+ stage:
+ type: string
+ enum:
+ - compile
+ - publish
+ description: Deployment stage that produced the log event, when available.
+ required:
+ - id
+ DatabaseQueryFilter:
+ type: object
+ description: One WHERE condition. Conditions are combined with AND.
+ properties:
+ column:
+ type: string
+ example: status
+ operator:
+ type: string
+ enum:
+ - eq
+ - neq
+ - gt
+ - gte
+ - lt
+ - lte
+ - like
+ - ilike
+ - is
+ - in
+ example: eq
+ description: |
+ Filter operators:
+ - eq: equals (=)
+ - neq: not equals (<>)
+ - gt: greater than (>)
+ - gte: greater than or equal (>=)
+ - lt: less than (<)
+ - lte: less than or equal (<=)
+ - like: pattern match (LIKE)
+ - ilike: case-insensitive pattern match (ILIKE)
+ - is: IS NULL / IS NOT NULL
+ - in: IN array
+ value:
+ oneOf:
+ - type: string
+ nullable: true
+ - type: number
+ - type: boolean
+ - type: array
+ description: Array of values, for the `in` operator
+ items:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ example: published
+ required:
+ - column
+ - operator
+ - value
+ DatabaseQueryOrder:
+ type: object
+ description: One ORDER BY clause.
+ properties:
+ column:
+ type: string
+ example: created_at
+ ascending:
+ type: boolean
+ default: true
+ example: false
+ nulls_first:
+ type: boolean
+ default: false
+ required:
+ - column
+ FunctionRuntimeDeployment:
+ type: object
+ required:
+ - file_extensions
+ - entrypoint
+ - handler
+ - dependency_manifests
+ properties:
+ file_extensions:
+ type: array
+ description: Source file extensions the CLI can use to detect this runtime.
+ items:
+ type: string
+ example:
+ - .js
+ - .mjs
+ entrypoint:
+ type: string
+ description: Archive path the CLI should use for a single-file function source.
+ example: index.js
+ handler:
+ type: string
+ description: Handler symbol the CLI should submit when deploying this runtime.
+ example: handler
+ dependency_manifests:
+ type: array
+ description: Dependency manifest files the CLI should include for hosted builds.
+ items:
+ type: string
+ example:
+ - package.json
+ - package-lock.json
+ AuthHostedPageDefaults:
+ type: object
+ required:
+ - html
+ - css
+ description: |
+ The starting point for an unsaved page: the theme shell we render for the
+ built-in page plus its stylesheet. Valid input to the update endpoint —
+ it carries no script, meta, or link tags.
+ properties:
+ html:
+ type: string
+ description: Body shell markup containing the runtime render root.
+ css:
+ type: string
+ description: The built-in stylesheet, themed by the customer.
+ AuthHostedPageRuntime:
+ type: object
+ required:
+ - root_id
+ - script
+ - mock_prelude
+ description: |
+ The server-owned behavior of a hosted page. Clients compose previews from
+ this instead of reimplementing the page, so a preview cannot drift from
+ what is actually served.
+ properties:
+ root_id:
+ type: string
+ description: Element id the runtime script renders into. Markup carrying it opts into the theme-shell contract.
+ script:
+ type: string
+ description: The runtime script injected into the rendered page.
+ mock_prelude:
+ type: string
+ description: Preview harness that supplies request params and stubs the hosted-auth API. Never served on a real page.
diff --git a/pyproject.toml b/pyproject.toml
index 8ab05476..fdd8bf16 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,20 +16,36 @@ classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.14",
+]
+dependencies = [
+ "attrs>=26.1.0",
+ "centrifuge-python>=0.6.0,<0.7.0",
+ "httpx>=0.28.1,<0.29.0",
+ "python-dateutil>=2.9.0.post0,<3.0.0",
+ "typing-extensions>=4.15.0",
]
-dependencies = []
[dependency-groups]
dev = [
+ "behave>=1.3.3,<2.0.0",
+ "build>=1.5.0,<2.0.0",
"mypy>=1.18.0",
+ "openapi-python-client==0.29.0",
"pytest>=8.3.0",
"ruff>=0.9.0",
+ "types-python-dateutil>=2.9.0.20250822",
]
[tool.mypy]
files = ["src"]
python_version = "3.11"
strict = true
+exclude = ["src/volcano_sdk/_generated/"]
[tool.ruff]
target-version = "py311"
+extend-exclude = ["src/volcano_sdk/_generated"]
+
+[tool.ruff.lint]
+extend-select = ["I"]
diff --git a/scripts/check_openapi.py b/scripts/check_openapi.py
new file mode 100755
index 00000000..69a306ff
--- /dev/null
+++ b/scripts/check_openapi.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import sys
+import tempfile
+from pathlib import Path
+
+from generate_openapi import DEFAULT_OUTPUT, generate
+
+
+def generated_files(root: Path) -> dict[Path, Path]:
+ return {
+ path.relative_to(root): path
+ for path in root.rglob("*")
+ if path.is_file()
+ and "__pycache__" not in path.parts
+ and path.suffix not in {".pyc", ".pyo"}
+ }
+
+
+def compared_files(left: Path, right: Path) -> tuple[list[str], list[str], list[str]]:
+ left_files = generated_files(left)
+ right_files = generated_files(right)
+ missing = [str(path) for path in sorted(left_files.keys() - right_files.keys())]
+ extra = [str(path) for path in sorted(right_files.keys() - left_files.keys())]
+ changed = [
+ str(path)
+ for path in sorted(left_files.keys() & right_files.keys())
+ if left_files[path].read_bytes() != right_files[path].read_bytes()
+ ]
+ return missing, extra, changed
+
+
+def main() -> None:
+ with tempfile.TemporaryDirectory(prefix="volcano-sdk-openapi-") as directory:
+ generated = Path(directory) / "_generated"
+ generate(generated)
+ missing, extra, changed = compared_files(DEFAULT_OUTPUT, generated)
+
+ if missing or extra or changed:
+ for label, paths in (
+ ("missing from regeneration", missing),
+ ("unexpected in regeneration", extra),
+ ("changed after regeneration", changed),
+ ):
+ for path in sorted(paths):
+ print(f"{label}: {path}", file=sys.stderr)
+ raise SystemExit(1)
+
+ print("OpenAPI generated client is up to date")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/generate_openapi.py b/scripts/generate_openapi.py
new file mode 100755
index 00000000..5a41bd53
--- /dev/null
+++ b/scripts/generate_openapi.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import shutil
+import subprocess
+import sys
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+SPEC = ROOT / "openapi" / "openapi.yaml"
+CONFIG = ROOT / "openapi-python-client.yaml"
+DEFAULT_OUTPUT = ROOT / "src" / "volcano_sdk" / "_generated"
+REQUIRED_OPERATION_MODULES = {
+ "acquire_project_lock.py",
+ "auth_signin.py",
+ "download_storage_object.py",
+ "query_database_select.py",
+ "release_project_lock.py",
+ "upload_storage_object.py",
+}
+
+
+def generate(output: Path) -> None:
+ if output.exists():
+ shutil.rmtree(output)
+ output.parent.mkdir(parents=True, exist_ok=True)
+ subprocess.run(
+ [
+ sys.executable,
+ "-m",
+ "openapi_python_client",
+ "generate",
+ "--path",
+ str(SPEC),
+ "--config",
+ str(CONFIG),
+ "--meta",
+ "none",
+ "--output-path",
+ str(output),
+ "--overwrite",
+ ],
+ cwd=ROOT,
+ check=True,
+ )
+ generated_operations = {path.name for path in (output / "api").rglob("*.py")}
+ missing = REQUIRED_OPERATION_MODULES - generated_operations
+ if missing:
+ raise RuntimeError(f"required OpenAPI operations were not generated: {sorted(missing)}")
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(description="Generate the internal OpenAPI client")
+ parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
+ args = parser.parse_args()
+ generate(args.output.resolve())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/volcano_sdk/__init__.py b/src/volcano_sdk/__init__.py
index ea24b86c..2b519c4c 100644
--- a/src/volcano_sdk/__init__.py
+++ b/src/volcano_sdk/__init__.py
@@ -1,3 +1,26 @@
from .client import VolcanoClient
+from .errors import (
+ AuthenticationError,
+ ConflictError,
+ NotFoundError,
+ RateLimitedError,
+ ServerError,
+ TransportError,
+ ValidationError,
+ VolcanoError,
+)
+from .models import LockLease, Session
-__all__ = ["VolcanoClient"]
+__all__ = [
+ "AuthenticationError",
+ "ConflictError",
+ "LockLease",
+ "NotFoundError",
+ "RateLimitedError",
+ "ServerError",
+ "Session",
+ "TransportError",
+ "ValidationError",
+ "VolcanoClient",
+ "VolcanoError",
+]
diff --git a/src/volcano_sdk/_generated/__init__.py b/src/volcano_sdk/_generated/__init__.py
new file mode 100644
index 00000000..ec037090
--- /dev/null
+++ b/src/volcano_sdk/_generated/__init__.py
@@ -0,0 +1,8 @@
+
+""" A client library for accessing Volcano Hosting API """
+from .client import AuthenticatedClient, Client
+
+__all__ = (
+ "AuthenticatedClient",
+ "Client",
+)
diff --git a/src/volcano_sdk/_generated/api/__init__.py b/src/volcano_sdk/_generated/api/__init__.py
new file mode 100644
index 00000000..dc035f4c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/__init__.py
@@ -0,0 +1 @@
+""" Contains methods for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/anon_keys/__init__.py b/src/volcano_sdk/_generated/api/anon_keys/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/anon_keys/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/anon_keys/create_anon_key.py b/src/volcano_sdk/_generated/api/anon_keys/create_anon_key.py
new file mode 100644
index 00000000..4ef89120
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/anon_keys/create_anon_key.py
@@ -0,0 +1,192 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.anon_key import AnonKey
+from ...models.create_anon_key_body import CreateAnonKeyBody
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateAnonKeyBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/anon-keys".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AnonKey | None:
+ if response.status_code == 201:
+ response_201 = AnonKey.from_dict(response.json())
+
+
+
+ return response_201
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AnonKey]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateAnonKeyBody,
+
+) -> Response[AnonKey]:
+ """ Create anon key
+
+ Args:
+ id (UUID):
+ body (CreateAnonKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateAnonKeyBody,
+
+) -> AnonKey | None:
+ """ Create anon key
+
+ Args:
+ id (UUID):
+ body (CreateAnonKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateAnonKeyBody,
+
+) -> Response[AnonKey]:
+ """ Create anon key
+
+ Args:
+ id (UUID):
+ body (CreateAnonKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateAnonKeyBody,
+
+) -> AnonKey | None:
+ """ Create anon key
+
+ Args:
+ id (UUID):
+ body (CreateAnonKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/anon_keys/get_anon_key.py b/src/volcano_sdk/_generated/api/anon_keys/get_anon_key.py
new file mode 100644
index 00000000..aa61b63a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/anon_keys/get_anon_key.py
@@ -0,0 +1,197 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.anon_key import AnonKey
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ key_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/anon-keys/{key_id}".format(id=quote(str(id), safe=""),key_id=quote(str(key_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AnonKey | Any | None:
+ if response.status_code == 200:
+ response_200 = AnonKey.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AnonKey | Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AnonKey | Any]:
+ """ Get anon key
+
+ Get details of a specific anon key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey | Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AnonKey | Any | None:
+ """ Get anon key
+
+ Get details of a specific anon key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey | Any
+ """
+
+
+ return sync_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AnonKey | Any]:
+ """ Get anon key
+
+ Get details of a specific anon key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey | Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AnonKey | Any | None:
+ """ Get anon key
+
+ Get details of a specific anon key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey | Any
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/anon_keys/list_anon_keys.py b/src/volcano_sdk/_generated/api/anon_keys/list_anon_keys.py
new file mode 100644
index 00000000..277ddb8c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/anon_keys/list_anon_keys.py
@@ -0,0 +1,297 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.list_anon_keys_response_200 import ListAnonKeysResponse200
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/anon-keys".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ListAnonKeysResponse200 | None:
+ if response.status_code == 200:
+ response_200 = ListAnonKeysResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ListAnonKeysResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[ListAnonKeysResponse200]:
+ """ List anon keys
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and is the default when neither `cursor` nor `search` is
+ supplied (first page, default `limit`). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListAnonKeysResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> ListAnonKeysResponse200 | None:
+ """ List anon keys
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and is the default when neither `cursor` nor `search` is
+ supplied (first page, default `limit`). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListAnonKeysResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[ListAnonKeysResponse200]:
+ """ List anon keys
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and is the default when neither `cursor` nor `search` is
+ supplied (first page, default `limit`). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListAnonKeysResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> ListAnonKeysResponse200 | None:
+ """ List anon keys
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and is the default when neither `cursor` nor `search` is
+ supplied (first page, default `limit`). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListAnonKeysResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/anon_keys/regenerate_anon_key.py b/src/volcano_sdk/_generated/api/anon_keys/regenerate_anon_key.py
new file mode 100644
index 00000000..d80401ab
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/anon_keys/regenerate_anon_key.py
@@ -0,0 +1,193 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.anon_key import AnonKey
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ key_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/anon-keys/{key_id}/regenerate".format(id=quote(str(id), safe=""),key_id=quote(str(key_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AnonKey | None:
+ if response.status_code == 200:
+ response_200 = AnonKey.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AnonKey]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AnonKey]:
+ """ Regenerate anon key
+
+ Generate new JWT value for existing key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AnonKey | None:
+ """ Regenerate anon key
+
+ Generate new JWT value for existing key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey
+ """
+
+
+ return sync_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AnonKey]:
+ """ Regenerate anon key
+
+ Generate new JWT value for existing key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AnonKey | None:
+ """ Regenerate anon key
+
+ Generate new JWT value for existing key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/anon_keys/revoke_anon_key.py b/src/volcano_sdk/_generated/api/anon_keys/revoke_anon_key.py
new file mode 100644
index 00000000..aeae38e1
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/anon_keys/revoke_anon_key.py
@@ -0,0 +1,216 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ key_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/anon-keys/{key_id}".format(id=quote(str(id), safe=""),key_id=quote(str(key_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Revoke anon key
+
+ Revokes key - it will immediately stop working
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Revoke anon key
+
+ Revokes key - it will immediately stop working
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Revoke anon key
+
+ Revokes key - it will immediately stop working
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Revoke anon key
+
+ Revokes key - it will immediately stop working
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/anon_keys/set_default_anon_key.py b/src/volcano_sdk/_generated/api/anon_keys/set_default_anon_key.py
new file mode 100644
index 00000000..18afff1b
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/anon_keys/set_default_anon_key.py
@@ -0,0 +1,217 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.anon_key import AnonKey
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ key_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/anon-keys/{key_id}/set-default".format(id=quote(str(id), safe=""),key_id=quote(str(key_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AnonKey | Any | Error | None:
+ if response.status_code == 200:
+ response_200 = AnonKey.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AnonKey | Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AnonKey | Any | Error]:
+ """ Set default anon key
+
+ Promotes the given key to the project's configured default. At most one key per project can be
+ default.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey | Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AnonKey | Any | Error | None:
+ """ Set default anon key
+
+ Promotes the given key to the project's configured default. At most one key per project can be
+ default.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey | Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AnonKey | Any | Error]:
+ """ Set default anon key
+
+ Promotes the given key to the project's configured default. At most one key per project can be
+ default.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AnonKey | Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AnonKey | Any | Error | None:
+ """ Set default anon key
+
+ Promotes the given key to the project's configured default. At most one key per project can be
+ default.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AnonKey | Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_admin/__init__.py b/src/volcano_sdk/_generated/api/auth_admin/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/auth_admin/ban_auth_user.py b/src/volcano_sdk/_generated/api/auth_admin/ban_auth_user.py
new file mode 100644
index 00000000..a1f305ad
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/ban_auth_user.py
@@ -0,0 +1,240 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.ban_auth_user_body import BanAuthUserBody
+from ...models.ban_user_response import BanUserResponse
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ user_id: UUID,
+ *,
+ body: BanAuthUserBody | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/auth/users/{user_id}/ban".format(id=quote(str(id), safe=""),user_id=quote(str(user_id), safe=""),),
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> BanUserResponse | Error | None:
+ if response.status_code == 200:
+ response_200 = BanUserResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[BanUserResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: BanAuthUserBody | Unset = UNSET,
+
+) -> Response[BanUserResponse | Error]:
+ """ Ban a user
+
+ Bans a user temporarily or permanently. Banned users cannot sign in
+ and all their active sessions are immediately revoked.
+
+ - Omit `banned_until` for a permanent ban
+ - Provide `banned_until` ISO timestamp for a temporary ban
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ body (BanAuthUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[BanUserResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: BanAuthUserBody | Unset = UNSET,
+
+) -> BanUserResponse | Error | None:
+ """ Ban a user
+
+ Bans a user temporarily or permanently. Banned users cannot sign in
+ and all their active sessions are immediately revoked.
+
+ - Omit `banned_until` for a permanent ban
+ - Provide `banned_until` ISO timestamp for a temporary ban
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ body (BanAuthUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ BanUserResponse | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: BanAuthUserBody | Unset = UNSET,
+
+) -> Response[BanUserResponse | Error]:
+ """ Ban a user
+
+ Bans a user temporarily or permanently. Banned users cannot sign in
+ and all their active sessions are immediately revoked.
+
+ - Omit `banned_until` for a permanent ban
+ - Provide `banned_until` ISO timestamp for a temporary ban
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ body (BanAuthUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[BanUserResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: BanAuthUserBody | Unset = UNSET,
+
+) -> BanUserResponse | Error | None:
+ """ Ban a user
+
+ Bans a user temporarily or permanently. Banned users cannot sign in
+ and all their active sessions are immediately revoked.
+
+ - Omit `banned_until` for a permanent ban
+ - Provide `banned_until` ISO timestamp for a temporary ban
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ body (BanAuthUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ BanUserResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_admin/delete_all_user_sessions.py b/src/volcano_sdk/_generated/api/auth_admin/delete_all_user_sessions.py
new file mode 100644
index 00000000..0ee3e579
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/delete_all_user_sessions.py
@@ -0,0 +1,132 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ user_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/auth/users/{user_id}/sessions".format(id=quote(str(id), safe=""),user_id=quote(str(user_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 204:
+ return None
+
+ if response.status_code == 404:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete all user sessions
+
+ Revokes all sessions for a user, forcing them to re-authenticate on all devices.
+ Use this to log out a user from everywhere.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete all user sessions
+
+ Revokes all sessions for a user, forcing them to re-authenticate on all devices.
+ Use this to log out a user from everywhere.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/auth_admin/delete_auth_user.py b/src/volcano_sdk/_generated/api/auth_admin/delete_auth_user.py
new file mode 100644
index 00000000..bc1a5e2c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/delete_auth_user.py
@@ -0,0 +1,127 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ user_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/auth/users/{user_id}".format(id=quote(str(id), safe=""),user_id=quote(str(user_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 204:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete auth user (admin)
+
+ Soft-deletes user and revokes all sessions
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete auth user (admin)
+
+ Soft-deletes user and revokes all sessions
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/auth_admin/delete_user_session.py b/src/volcano_sdk/_generated/api/auth_admin/delete_user_session.py
new file mode 100644
index 00000000..61c04ffd
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/delete_user_session.py
@@ -0,0 +1,139 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ user_id: UUID,
+ session_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/auth/users/{user_id}/sessions/{session_id}".format(id=quote(str(id), safe=""),user_id=quote(str(user_id), safe=""),session_id=quote(str(session_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 204:
+ return None
+
+ if response.status_code == 404:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ user_id: UUID,
+ session_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete specific session
+
+ Revokes a specific session for a user.
+ Use this to log out a user from a single device.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ session_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+session_id=session_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ user_id: UUID,
+ session_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete specific session
+
+ Revokes a specific session for a user.
+ Use this to log out a user from a single device.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ session_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+session_id=session_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/auth_admin/get_auth_insights.py b/src/volcano_sdk/_generated/api/auth_admin/get_auth_insights.py
new file mode 100644
index 00000000..8dcaf6fd
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/get_auth_insights.py
@@ -0,0 +1,301 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_insights_interval import AuthInsightsInterval
+from ...models.auth_insights_interval import check_auth_insights_interval
+from ...models.auth_insights_response import AuthInsightsResponse
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ from_: datetime.date | Unset = UNSET,
+ to: datetime.date | Unset = UNSET,
+ interval: AuthInsightsInterval | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_from_: str | Unset = UNSET
+ if not isinstance(from_, Unset):
+ json_from_ = from_.isoformat()
+ params["from"] = json_from_
+
+ json_to: str | Unset = UNSET
+ if not isinstance(to, Unset):
+ json_to = to.isoformat()
+ params["to"] = json_to
+
+ json_interval: str | Unset = UNSET
+ if not isinstance(interval, Unset):
+ json_interval = interval
+
+ params["interval"] = json_interval
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/insights".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthInsightsResponse | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthInsightsResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthInsightsResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.date | Unset = UNSET,
+ to: datetime.date | Unset = UNSET,
+ interval: AuthInsightsInterval | Unset = UNSET,
+
+) -> Response[AuthInsightsResponse | Error]:
+ """ Get auth user insights
+
+ Returns current auth-user totals, rolling 30-day active users, and
+ zero-filled signup and successful sign-in counts for an inclusive UTC
+ date range. Weeks start on Monday. Sign-in counts and active-user
+ activity begin when collection is deployed. Historical signup counts
+ are backfilled from users present at deployment. Token refreshes affect
+ active users but not the sign-in series.
+
+ Args:
+ id (UUID):
+ from_ (datetime.date | Unset):
+ to (datetime.date | Unset):
+ interval (AuthInsightsInterval | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthInsightsResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+from_=from_,
+to=to,
+interval=interval,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.date | Unset = UNSET,
+ to: datetime.date | Unset = UNSET,
+ interval: AuthInsightsInterval | Unset = UNSET,
+
+) -> AuthInsightsResponse | Error | None:
+ """ Get auth user insights
+
+ Returns current auth-user totals, rolling 30-day active users, and
+ zero-filled signup and successful sign-in counts for an inclusive UTC
+ date range. Weeks start on Monday. Sign-in counts and active-user
+ activity begin when collection is deployed. Historical signup counts
+ are backfilled from users present at deployment. Token refreshes affect
+ active users but not the sign-in series.
+
+ Args:
+ id (UUID):
+ from_ (datetime.date | Unset):
+ to (datetime.date | Unset):
+ interval (AuthInsightsInterval | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthInsightsResponse | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+from_=from_,
+to=to,
+interval=interval,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.date | Unset = UNSET,
+ to: datetime.date | Unset = UNSET,
+ interval: AuthInsightsInterval | Unset = UNSET,
+
+) -> Response[AuthInsightsResponse | Error]:
+ """ Get auth user insights
+
+ Returns current auth-user totals, rolling 30-day active users, and
+ zero-filled signup and successful sign-in counts for an inclusive UTC
+ date range. Weeks start on Monday. Sign-in counts and active-user
+ activity begin when collection is deployed. Historical signup counts
+ are backfilled from users present at deployment. Token refreshes affect
+ active users but not the sign-in series.
+
+ Args:
+ id (UUID):
+ from_ (datetime.date | Unset):
+ to (datetime.date | Unset):
+ interval (AuthInsightsInterval | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthInsightsResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+from_=from_,
+to=to,
+interval=interval,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.date | Unset = UNSET,
+ to: datetime.date | Unset = UNSET,
+ interval: AuthInsightsInterval | Unset = UNSET,
+
+) -> AuthInsightsResponse | Error | None:
+ """ Get auth user insights
+
+ Returns current auth-user totals, rolling 30-day active users, and
+ zero-filled signup and successful sign-in counts for an inclusive UTC
+ date range. Weeks start on Monday. Sign-in counts and active-user
+ activity begin when collection is deployed. Historical signup counts
+ are backfilled from users present at deployment. Token refreshes affect
+ active users but not the sign-in series.
+
+ Args:
+ id (UUID):
+ from_ (datetime.date | Unset):
+ to (datetime.date | Unset):
+ interval (AuthInsightsInterval | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthInsightsResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+from_=from_,
+to=to,
+interval=interval,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_admin/get_auth_user.py b/src/volcano_sdk/_generated/api/auth_admin/get_auth_user.py
new file mode 100644
index 00000000..9535b7e9
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/get_auth_user.py
@@ -0,0 +1,185 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_user import AuthUser
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ user_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/users/{user_id}".format(id=quote(str(id), safe=""),user_id=quote(str(user_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthUser | None:
+ if response.status_code == 200:
+ response_200 = AuthUser.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthUser]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthUser]:
+ """ Get specific auth user (admin)
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthUser]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthUser | None:
+ """ Get specific auth user (admin)
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthUser
+ """
+
+
+ return sync_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthUser]:
+ """ Get specific auth user (admin)
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthUser]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthUser | None:
+ """ Get specific auth user (admin)
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthUser
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_admin/list_auth_users.py b/src/volcano_sdk/_generated/api/auth_admin/list_auth_users.py
new file mode 100644
index 00000000..ba7d4719
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/list_auth_users.py
@@ -0,0 +1,306 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.list_auth_users_status import check_list_auth_users_status
+from ...models.list_auth_users_status import ListAuthUsersStatus
+from ...models.paginated_auth_users import PaginatedAuthUsers
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ status: ListAuthUsersStatus | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+ json_status: str | Unset = UNSET
+ if not isinstance(status, Unset):
+ json_status = status
+
+ params["status"] = json_status
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/users".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedAuthUsers | None:
+ if response.status_code == 200:
+ response_200 = PaginatedAuthUsers.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedAuthUsers]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ status: ListAuthUsersStatus | Unset = UNSET,
+
+) -> Response[Error | PaginatedAuthUsers]:
+ """ List all auth users (admin)
+
+ List auth users in project. Requires platform token.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ status (ListAuthUsersStatus | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedAuthUsers]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+status=status,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ status: ListAuthUsersStatus | Unset = UNSET,
+
+) -> Error | PaginatedAuthUsers | None:
+ """ List all auth users (admin)
+
+ List auth users in project. Requires platform token.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ status (ListAuthUsersStatus | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedAuthUsers
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+status=status,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ status: ListAuthUsersStatus | Unset = UNSET,
+
+) -> Response[Error | PaginatedAuthUsers]:
+ """ List all auth users (admin)
+
+ List auth users in project. Requires platform token.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ status (ListAuthUsersStatus | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedAuthUsers]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+status=status,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ status: ListAuthUsersStatus | Unset = UNSET,
+
+) -> Error | PaginatedAuthUsers | None:
+ """ List all auth users (admin)
+
+ List auth users in project. Requires platform token.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ status (ListAuthUsersStatus | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedAuthUsers
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+status=status,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_admin/list_user_sessions.py b/src/volcano_sdk/_generated/api/auth_admin/list_user_sessions.py
new file mode 100644
index 00000000..15382bbb
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/list_user_sessions.py
@@ -0,0 +1,365 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.list_user_sessions_response_200 import ListUserSessionsResponse200
+from ...models.list_user_sessions_sort import check_list_user_sessions_sort
+from ...models.list_user_sessions_sort import ListUserSessionsSort
+from ...models.list_user_sessions_status import check_list_user_sessions_status
+from ...models.list_user_sessions_status import ListUserSessionsStatus
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ user_id: UUID,
+ *,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: ListUserSessionsSort | Unset = 'last_activity',
+ status: ListUserSessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ json_sort: str | Unset = UNSET
+ if not isinstance(sort, Unset):
+ json_sort = sort
+
+ params["sort"] = json_sort
+
+ json_status: str | Unset = UNSET
+ if not isinstance(status, Unset):
+ json_status = status
+
+ params["status"] = json_status
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/users/{user_id}/sessions".format(id=quote(str(id), safe=""),user_id=quote(str(user_id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | ListUserSessionsResponse200 | None:
+ if response.status_code == 200:
+ response_200 = ListUserSessionsResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error | ListUserSessionsResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: ListUserSessionsSort | Unset = 'last_activity',
+ status: ListUserSessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> Response[Any | Error | ListUserSessionsResponse200]:
+ """ List user sessions
+
+ List paginated sessions for a specific auth user.
+ Returns session details including device info, IP address, and activity timestamps.
+
+ Ordering and pagination match `GET /auth/user/sessions`: the default is
+ activity order with `page`/`limit` and the legacy `sessions` body, and
+ `sort=created_at` opts into the standard cursor/offset hybrid with the
+ shared `data` envelope. Cursor pagination is only available for
+ `sort=created_at`, because the activity timestamp changes under paging.
+ The `status=expired` filter is offset-only because sessions can expire
+ above a cursor anchor during a walk.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (ListUserSessionsSort | Unset): Default: 'last_activity'.
+ status (ListUserSessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | ListUserSessionsResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: ListUserSessionsSort | Unset = 'last_activity',
+ status: ListUserSessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> Any | Error | ListUserSessionsResponse200 | None:
+ """ List user sessions
+
+ List paginated sessions for a specific auth user.
+ Returns session details including device info, IP address, and activity timestamps.
+
+ Ordering and pagination match `GET /auth/user/sessions`: the default is
+ activity order with `page`/`limit` and the legacy `sessions` body, and
+ `sort=created_at` opts into the standard cursor/offset hybrid with the
+ shared `data` envelope. Cursor pagination is only available for
+ `sort=created_at`, because the activity timestamp changes under paging.
+ The `status=expired` filter is offset-only because sessions can expire
+ above a cursor anchor during a walk.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (ListUserSessionsSort | Unset): Default: 'last_activity'.
+ status (ListUserSessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | ListUserSessionsResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: ListUserSessionsSort | Unset = 'last_activity',
+ status: ListUserSessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> Response[Any | Error | ListUserSessionsResponse200]:
+ """ List user sessions
+
+ List paginated sessions for a specific auth user.
+ Returns session details including device info, IP address, and activity timestamps.
+
+ Ordering and pagination match `GET /auth/user/sessions`: the default is
+ activity order with `page`/`limit` and the legacy `sessions` body, and
+ `sort=created_at` opts into the standard cursor/offset hybrid with the
+ shared `data` envelope. Cursor pagination is only available for
+ `sort=created_at`, because the activity timestamp changes under paging.
+ The `status=expired` filter is offset-only because sessions can expire
+ above a cursor anchor during a walk.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (ListUserSessionsSort | Unset): Default: 'last_activity'.
+ status (ListUserSessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | ListUserSessionsResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: ListUserSessionsSort | Unset = 'last_activity',
+ status: ListUserSessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> Any | Error | ListUserSessionsResponse200 | None:
+ """ List user sessions
+
+ List paginated sessions for a specific auth user.
+ Returns session details including device info, IP address, and activity timestamps.
+
+ Ordering and pagination match `GET /auth/user/sessions`: the default is
+ activity order with `page`/`limit` and the legacy `sessions` body, and
+ `sort=created_at` opts into the standard cursor/offset hybrid with the
+ shared `data` envelope. Cursor pagination is only available for
+ `sort=created_at`, because the activity timestamp changes under paging.
+ The `status=expired` filter is offset-only because sessions can expire
+ above a cursor anchor during a walk.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (ListUserSessionsSort | Unset): Default: 'last_activity'.
+ status (ListUserSessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | ListUserSessionsResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_admin/unban_auth_user.py b/src/volcano_sdk/_generated/api/auth_admin/unban_auth_user.py
new file mode 100644
index 00000000..049af3b1
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_admin/unban_auth_user.py
@@ -0,0 +1,205 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.unban_user_response import UnbanUserResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ user_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/auth/users/{user_id}/unban".format(id=quote(str(id), safe=""),user_id=quote(str(user_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | UnbanUserResponse | None:
+ if response.status_code == 200:
+ response_200 = UnbanUserResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | UnbanUserResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | UnbanUserResponse]:
+ """ Unban a user
+
+ Removes a ban from a user, restoring their ability to sign in.
+ The user's status is set back to 'active'.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | UnbanUserResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | UnbanUserResponse | None:
+ """ Unban a user
+
+ Removes a ban from a user, restoring their ability to sign in.
+ The user's status is set back to 'active'.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | UnbanUserResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | UnbanUserResponse]:
+ """ Unban a user
+
+ Removes a ban from a user, restoring their ability to sign in.
+ The user's status is set back to 'active'.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | UnbanUserResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+user_id=user_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ user_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | UnbanUserResponse | None:
+ """ Unban a user
+
+ Removes a ban from a user, restoring their ability to sign in.
+ The user's status is set back to 'active'.
+
+ Args:
+ id (UUID):
+ user_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | UnbanUserResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+user_id=user_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/__init__.py b/src/volcano_sdk/_generated/api/auth_configuration/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/configure_auth_methods.py b/src/volcano_sdk/_generated/api/auth_configuration/configure_auth_methods.py
new file mode 100644
index 00000000..e0af1fd6
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/configure_auth_methods.py
@@ -0,0 +1,143 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.configure_auth_methods_body import ConfigureAuthMethodsBody
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: ConfigureAuthMethodsBody | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/auth/methods".format(id=quote(str(id), safe=""),),
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 200:
+ return None
+
+ if response.status_code == 400:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ConfigureAuthMethodsBody | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Configure authentication methods (unified)
+
+ Configure all authentication methods in a single request.
+ At least one method must remain enabled.
+
+ Args:
+ id (UUID):
+ body (ConfigureAuthMethodsBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ConfigureAuthMethodsBody | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Configure authentication methods (unified)
+
+ Configure all authentication methods in a single request.
+ At least one method must remain enabled.
+
+ Args:
+ id (UUID):
+ body (ConfigureAuthMethodsBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/create_email_template.py b/src/volcano_sdk/_generated/api/auth_configuration/create_email_template.py
new file mode 100644
index 00000000..dd5f81c9
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/create_email_template.py
@@ -0,0 +1,246 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_email_template_request import CreateEmailTemplateRequest
+from ...models.email_template import EmailTemplate
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateEmailTemplateRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/email-templates".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> EmailTemplate | Error | None:
+ if response.status_code == 201:
+ response_201 = EmailTemplate.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[EmailTemplate | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateEmailTemplateRequest,
+
+) -> Response[EmailTemplate | Error]:
+ """ Create email template
+
+ Creates a custom email template for the project. Custom email templates
+ are a PRO-plan feature: requests from a FREE-plan project owner are
+ rejected with 403, and FREE projects always send the built-in default
+ templates regardless of any previously saved custom rows.
+ Every project is created with one template per type, so customizing one
+ is usually a PUT; creating a type the project already has returns 409.
+ Valid template types: welcome, confirmation, password_reset, password_changed
+
+ Args:
+ id (UUID):
+ body (CreateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[EmailTemplate | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateEmailTemplateRequest,
+
+) -> EmailTemplate | Error | None:
+ """ Create email template
+
+ Creates a custom email template for the project. Custom email templates
+ are a PRO-plan feature: requests from a FREE-plan project owner are
+ rejected with 403, and FREE projects always send the built-in default
+ templates regardless of any previously saved custom rows.
+ Every project is created with one template per type, so customizing one
+ is usually a PUT; creating a type the project already has returns 409.
+ Valid template types: welcome, confirmation, password_reset, password_changed
+
+ Args:
+ id (UUID):
+ body (CreateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ EmailTemplate | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateEmailTemplateRequest,
+
+) -> Response[EmailTemplate | Error]:
+ """ Create email template
+
+ Creates a custom email template for the project. Custom email templates
+ are a PRO-plan feature: requests from a FREE-plan project owner are
+ rejected with 403, and FREE projects always send the built-in default
+ templates regardless of any previously saved custom rows.
+ Every project is created with one template per type, so customizing one
+ is usually a PUT; creating a type the project already has returns 409.
+ Valid template types: welcome, confirmation, password_reset, password_changed
+
+ Args:
+ id (UUID):
+ body (CreateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[EmailTemplate | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateEmailTemplateRequest,
+
+) -> EmailTemplate | Error | None:
+ """ Create email template
+
+ Creates a custom email template for the project. Custom email templates
+ are a PRO-plan feature: requests from a FREE-plan project owner are
+ rejected with 403, and FREE projects always send the built-in default
+ templates regardless of any previously saved custom rows.
+ Every project is created with one template per type, so customizing one
+ is usually a PUT; creating a type the project already has returns 409.
+ Valid template types: welcome, confirmation, password_reset, password_changed
+
+ Args:
+ id (UUID):
+ body (CreateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ EmailTemplate | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/delete_email_template.py b/src/volcano_sdk/_generated/api/auth_configuration/delete_email_template.py
new file mode 100644
index 00000000..13a478b5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/delete_email_template.py
@@ -0,0 +1,211 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.delete_email_template_type import check_delete_email_template_type
+from ...models.delete_email_template_type import DeleteEmailTemplateType
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ type_: DeleteEmailTemplateType,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/email-templates/{type_}".format(id=quote(str(id), safe=""),type_=quote(str(type_), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ type_: DeleteEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete email template
+
+ Deletes a custom template, reverting to the default. Custom email
+ templates are a PRO-plan feature: requests from a FREE-plan project owner
+ are rejected with 403.
+
+ Args:
+ id (UUID):
+ type_ (DeleteEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+type_=type_,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ type_: DeleteEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete email template
+
+ Deletes a custom template, reverting to the default. Custom email
+ templates are a PRO-plan feature: requests from a FREE-plan project owner
+ are rejected with 403.
+
+ Args:
+ id (UUID):
+ type_ (DeleteEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+type_=type_,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ type_: DeleteEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete email template
+
+ Deletes a custom template, reverting to the default. Custom email
+ templates are a PRO-plan feature: requests from a FREE-plan project owner
+ are rejected with 403.
+
+ Args:
+ id (UUID):
+ type_ (DeleteEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+type_=type_,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ type_: DeleteEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete email template
+
+ Deletes a custom template, reverting to the default. Custom email
+ templates are a PRO-plan feature: requests from a FREE-plan project owner
+ are rejected with 403.
+
+ Args:
+ id (UUID):
+ type_ (DeleteEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+type_=type_,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/get_auth_config.py b/src/volcano_sdk/_generated/api/auth_configuration/get_auth_config.py
new file mode 100644
index 00000000..ae759579
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/get_auth_config.py
@@ -0,0 +1,172 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_config import AuthConfig
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/config".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthConfig | None:
+ if response.status_code == 200:
+ response_200 = AuthConfig.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthConfig]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthConfig]:
+ """ Get auth configuration
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthConfig | None:
+ """ Get auth configuration
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthConfig
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthConfig]:
+ """ Get auth configuration
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthConfig | None:
+ """ Get auth configuration
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthConfig
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/get_auth_hosted_page.py b/src/volcano_sdk/_generated/api/auth_configuration/get_auth_hosted_page.py
new file mode 100644
index 00000000..9899b0b4
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/get_auth_hosted_page.py
@@ -0,0 +1,207 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_hosted_page_response import AuthHostedPageResponse
+from ...models.hosted_auth_page_type import check_hosted_auth_page_type
+from ...models.hosted_auth_page_type import HostedAuthPageType
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ page_type: HostedAuthPageType,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/hosted-pages/{page_type}".format(id=quote(str(id), safe=""),page_type=quote(str(page_type), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthHostedPageResponse | None:
+ if response.status_code == 200:
+ response_200 = AuthHostedPageResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthHostedPageResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthHostedPageResponse]:
+ """ Get hosted auth page
+
+ Returns the saved HTML/CSS for the page type, or `page: null` when the
+ project has not customized it yet. Always returns `defaults` (the theme
+ shell to seed an editor with, which is valid input to the update endpoint)
+ and `runtime` (the script the rendered page runs, plus a preview harness).
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthHostedPageResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page_type=page_type,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthHostedPageResponse | None:
+ """ Get hosted auth page
+
+ Returns the saved HTML/CSS for the page type, or `page: null` when the
+ project has not customized it yet. Always returns `defaults` (the theme
+ shell to seed an editor with, which is valid input to the update endpoint)
+ and `runtime` (the script the rendered page runs, plus a preview harness).
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthHostedPageResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+page_type=page_type,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthHostedPageResponse]:
+ """ Get hosted auth page
+
+ Returns the saved HTML/CSS for the page type, or `page: null` when the
+ project has not customized it yet. Always returns `defaults` (the theme
+ shell to seed an editor with, which is valid input to the update endpoint)
+ and `runtime` (the script the rendered page runs, plus a preview harness).
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthHostedPageResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page_type=page_type,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthHostedPageResponse | None:
+ """ Get hosted auth page
+
+ Returns the saved HTML/CSS for the page type, or `page: null` when the
+ project has not customized it yet. Always returns `defaults` (the theme
+ shell to seed an editor with, which is valid input to the update endpoint)
+ and `runtime` (the script the rendered page runs, plus a preview harness).
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthHostedPageResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+page_type=page_type,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/get_auth_methods.py b/src/volcano_sdk/_generated/api/auth_configuration/get_auth_methods.py
new file mode 100644
index 00000000..0c446a1d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/get_auth_methods.py
@@ -0,0 +1,184 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.get_auth_methods_response_200 import GetAuthMethodsResponse200
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/methods".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> GetAuthMethodsResponse200 | None:
+ if response.status_code == 200:
+ response_200 = GetAuthMethodsResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[GetAuthMethodsResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[GetAuthMethodsResponse200]:
+ """ Get all authentication methods
+
+ Returns all configured authentication methods for this project,
+ including email/password, anonymous, device authorization, and OAuth providers.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetAuthMethodsResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> GetAuthMethodsResponse200 | None:
+ """ Get all authentication methods
+
+ Returns all configured authentication methods for this project,
+ including email/password, anonymous, device authorization, and OAuth providers.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetAuthMethodsResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[GetAuthMethodsResponse200]:
+ """ Get all authentication methods
+
+ Returns all configured authentication methods for this project,
+ including email/password, anonymous, device authorization, and OAuth providers.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetAuthMethodsResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> GetAuthMethodsResponse200 | None:
+ """ Get all authentication methods
+
+ Returns all configured authentication methods for this project,
+ including email/password, anonymous, device authorization, and OAuth providers.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetAuthMethodsResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/get_default_email_template.py b/src/volcano_sdk/_generated/api/auth_configuration/get_default_email_template.py
new file mode 100644
index 00000000..1c77a8e5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/get_default_email_template.py
@@ -0,0 +1,177 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.email_template import EmailTemplate
+from ...models.get_default_email_template_type import check_get_default_email_template_type
+from ...models.get_default_email_template_type import GetDefaultEmailTemplateType
+from typing import cast
+
+
+
+def _get_kwargs(
+ type_: GetDefaultEmailTemplateType,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/email-templates/defaults/{type_}".format(type_=quote(str(type_), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | EmailTemplate | None:
+ if response.status_code == 200:
+ response_200 = EmailTemplate.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | EmailTemplate]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ type_: GetDefaultEmailTemplateType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Any | EmailTemplate]:
+ """ Get default email template by type
+
+ Args:
+ type_ (GetDefaultEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | EmailTemplate]
+ """
+
+
+ kwargs = _get_kwargs(
+ type_=type_,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ type_: GetDefaultEmailTemplateType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Any | EmailTemplate | None:
+ """ Get default email template by type
+
+ Args:
+ type_ (GetDefaultEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | EmailTemplate
+ """
+
+
+ return sync_detailed(
+ type_=type_,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ type_: GetDefaultEmailTemplateType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Any | EmailTemplate]:
+ """ Get default email template by type
+
+ Args:
+ type_ (GetDefaultEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | EmailTemplate]
+ """
+
+
+ kwargs = _get_kwargs(
+ type_=type_,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ type_: GetDefaultEmailTemplateType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Any | EmailTemplate | None:
+ """ Get default email template by type
+
+ Args:
+ type_ (GetDefaultEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | EmailTemplate
+ """
+
+
+ return (await asyncio_detailed(
+ type_=type_,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/get_default_email_templates.py b/src/volcano_sdk/_generated/api/auth_configuration/get_default_email_templates.py
new file mode 100644
index 00000000..fff7b9f2
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/get_default_email_templates.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.get_default_email_templates_response_200 import GetDefaultEmailTemplatesResponse200
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/email-templates/defaults",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> GetDefaultEmailTemplatesResponse200 | None:
+ if response.status_code == 200:
+ response_200 = GetDefaultEmailTemplatesResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[GetDefaultEmailTemplatesResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[GetDefaultEmailTemplatesResponse200]:
+ """ Get default email templates
+
+ Returns the default email templates used when no custom template is configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetDefaultEmailTemplatesResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> GetDefaultEmailTemplatesResponse200 | None:
+ """ Get default email templates
+
+ Returns the default email templates used when no custom template is configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetDefaultEmailTemplatesResponse200
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[GetDefaultEmailTemplatesResponse200]:
+ """ Get default email templates
+
+ Returns the default email templates used when no custom template is configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetDefaultEmailTemplatesResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> GetDefaultEmailTemplatesResponse200 | None:
+ """ Get default email templates
+
+ Returns the default email templates used when no custom template is configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetDefaultEmailTemplatesResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/get_email_template.py b/src/volcano_sdk/_generated/api/auth_configuration/get_email_template.py
new file mode 100644
index 00000000..2f516ed1
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/get_email_template.py
@@ -0,0 +1,191 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.email_template import EmailTemplate
+from ...models.get_email_template_type import check_get_email_template_type
+from ...models.get_email_template_type import GetEmailTemplateType
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ type_: GetEmailTemplateType,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/email-templates/{type_}".format(id=quote(str(id), safe=""),type_=quote(str(type_), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | EmailTemplate | None:
+ if response.status_code == 200:
+ response_200 = EmailTemplate.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | EmailTemplate]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ type_: GetEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | EmailTemplate]:
+ """ Get email template
+
+ Args:
+ id (UUID):
+ type_ (GetEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | EmailTemplate]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+type_=type_,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ type_: GetEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | EmailTemplate | None:
+ """ Get email template
+
+ Args:
+ id (UUID):
+ type_ (GetEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | EmailTemplate
+ """
+
+
+ return sync_detailed(
+ id=id,
+type_=type_,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ type_: GetEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | EmailTemplate]:
+ """ Get email template
+
+ Args:
+ id (UUID):
+ type_ (GetEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | EmailTemplate]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+type_=type_,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ type_: GetEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | EmailTemplate | None:
+ """ Get email template
+
+ Args:
+ id (UUID):
+ type_ (GetEmailTemplateType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | EmailTemplate
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+type_=type_,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/get_hosted_login_options.py b/src/volcano_sdk/_generated/api/auth_configuration/get_hosted_login_options.py
new file mode 100644
index 00000000..3172f3c1
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/get_hosted_login_options.py
@@ -0,0 +1,221 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.hosted_login_options_response import HostedLoginOptionsResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ anon_key: str,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["anon_key"] = anon_key
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/hosted/login/options".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | HostedLoginOptionsResponse | None:
+ if response.status_code == 200:
+ response_200 = HostedLoginOptionsResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = cast(Any, None)
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | HostedLoginOptionsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ anon_key: str,
+
+) -> Response[Any | HostedLoginOptionsResponse]:
+ """ Get hosted login runtime options
+
+ Returns runtime options for the built-in managed login flow.
+ Requires `anon_key` query parameter.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ anon_key (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | HostedLoginOptionsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+anon_key=anon_key,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ anon_key: str,
+
+) -> Any | HostedLoginOptionsResponse | None:
+ """ Get hosted login runtime options
+
+ Returns runtime options for the built-in managed login flow.
+ Requires `anon_key` query parameter.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ anon_key (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | HostedLoginOptionsResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+anon_key=anon_key,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ anon_key: str,
+
+) -> Response[Any | HostedLoginOptionsResponse]:
+ """ Get hosted login runtime options
+
+ Returns runtime options for the built-in managed login flow.
+ Requires `anon_key` query parameter.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ anon_key (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | HostedLoginOptionsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+anon_key=anon_key,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ anon_key: str,
+
+) -> Any | HostedLoginOptionsResponse | None:
+ """ Get hosted login runtime options
+
+ Returns runtime options for the built-in managed login flow.
+ Requires `anon_key` query parameter.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ anon_key (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | HostedLoginOptionsResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+anon_key=anon_key,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/hosted_login_check_email.py b/src/volcano_sdk/_generated/api/auth_configuration/hosted_login_check_email.py
new file mode 100644
index 00000000..15ea8f07
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/hosted_login_check_email.py
@@ -0,0 +1,231 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.hosted_login_email_check_request import HostedLoginEmailCheckRequest
+from ...models.hosted_login_email_check_response import HostedLoginEmailCheckResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: HostedLoginEmailCheckRequest,
+ authorization: str,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["Authorization"] = authorization
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/auth/hosted/login/check-email".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | HostedLoginEmailCheckResponse | None:
+ if response.status_code == 200:
+ response_200 = HostedLoginEmailCheckResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 429:
+ response_429 = cast(Any, None)
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | HostedLoginEmailCheckResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ body: HostedLoginEmailCheckRequest,
+ authorization: str,
+
+) -> Response[Any | HostedLoginEmailCheckResponse]:
+ """ Check whether email exists for hosted login flow
+
+ Used by the built-in managed login page to branch UI between signin and signup.
+ Requires anon key in Authorization header.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ authorization (str):
+ body (HostedLoginEmailCheckRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | HostedLoginEmailCheckResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+authorization=authorization,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ body: HostedLoginEmailCheckRequest,
+ authorization: str,
+
+) -> Any | HostedLoginEmailCheckResponse | None:
+ """ Check whether email exists for hosted login flow
+
+ Used by the built-in managed login page to branch UI between signin and signup.
+ Requires anon key in Authorization header.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ authorization (str):
+ body (HostedLoginEmailCheckRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | HostedLoginEmailCheckResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+authorization=authorization,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ body: HostedLoginEmailCheckRequest,
+ authorization: str,
+
+) -> Response[Any | HostedLoginEmailCheckResponse]:
+ """ Check whether email exists for hosted login flow
+
+ Used by the built-in managed login page to branch UI between signin and signup.
+ Requires anon key in Authorization header.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ authorization (str):
+ body (HostedLoginEmailCheckRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | HostedLoginEmailCheckResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+authorization=authorization,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ body: HostedLoginEmailCheckRequest,
+ authorization: str,
+
+) -> Any | HostedLoginEmailCheckResponse | None:
+ """ Check whether email exists for hosted login flow
+
+ Used by the built-in managed login page to branch UI between signin and signup.
+ Requires anon key in Authorization header.
+ Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
+
+ Args:
+ id (UUID):
+ authorization (str):
+ body (HostedLoginEmailCheckRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | HostedLoginEmailCheckResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+authorization=authorization,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/list_email_templates.py b/src/volcano_sdk/_generated/api/auth_configuration/list_email_templates.py
new file mode 100644
index 00000000..f7b2a961
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/list_email_templates.py
@@ -0,0 +1,180 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.list_email_templates_response_200 import ListEmailTemplatesResponse200
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/email-templates".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ListEmailTemplatesResponse200 | None:
+ if response.status_code == 200:
+ response_200 = ListEmailTemplatesResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ListEmailTemplatesResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ListEmailTemplatesResponse200]:
+ """ List email templates
+
+ Returns all custom email templates for this project.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListEmailTemplatesResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ListEmailTemplatesResponse200 | None:
+ """ List email templates
+
+ Returns all custom email templates for this project.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListEmailTemplatesResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ListEmailTemplatesResponse200]:
+ """ List email templates
+
+ Returns all custom email templates for this project.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListEmailTemplatesResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ListEmailTemplatesResponse200 | None:
+ """ List email templates
+
+ Returns all custom email templates for this project.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListEmailTemplatesResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/render_default_managed_auth_page.py b/src/volcano_sdk/_generated/api/auth_configuration/render_default_managed_auth_page.py
new file mode 100644
index 00000000..fd05b4fa
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/render_default_managed_auth_page.py
@@ -0,0 +1,261 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.render_default_managed_auth_page_action import check_render_default_managed_auth_page_action
+from ...models.render_default_managed_auth_page_action import RenderDefaultManagedAuthPageAction
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ action: RenderDefaultManagedAuthPageAction | Unset = UNSET,
+ user_code: str | Unset = UNSET,
+ anon_key: str | Unset = UNSET,
+ state: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_action: str | Unset = UNSET
+ if not isinstance(action, Unset):
+ json_action = action
+
+ params["action"] = json_action
+
+ params["user_code"] = user_code
+
+ params["anon_key"] = anon_key
+
+ params["state"] = state
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/hosted".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | str | None:
+ if response.status_code == 200:
+ response_200 = response.text
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | str]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ action: RenderDefaultManagedAuthPageAction | Unset = UNSET,
+ user_code: str | Unset = UNSET,
+ anon_key: str | Unset = UNSET,
+ state: str | Unset = UNSET,
+
+) -> Response[Any | str]:
+ """ Render default managed auth page
+
+ Public HTML endpoint for the managed login page.
+ Requires `Accept: text/html`.
+
+ Args:
+ id (UUID):
+ action (RenderDefaultManagedAuthPageAction | Unset):
+ user_code (str | Unset):
+ anon_key (str | Unset):
+ state (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | str]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+action=action,
+user_code=user_code,
+anon_key=anon_key,
+state=state,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ action: RenderDefaultManagedAuthPageAction | Unset = UNSET,
+ user_code: str | Unset = UNSET,
+ anon_key: str | Unset = UNSET,
+ state: str | Unset = UNSET,
+
+) -> Any | str | None:
+ """ Render default managed auth page
+
+ Public HTML endpoint for the managed login page.
+ Requires `Accept: text/html`.
+
+ Args:
+ id (UUID):
+ action (RenderDefaultManagedAuthPageAction | Unset):
+ user_code (str | Unset):
+ anon_key (str | Unset):
+ state (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | str
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+action=action,
+user_code=user_code,
+anon_key=anon_key,
+state=state,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ action: RenderDefaultManagedAuthPageAction | Unset = UNSET,
+ user_code: str | Unset = UNSET,
+ anon_key: str | Unset = UNSET,
+ state: str | Unset = UNSET,
+
+) -> Response[Any | str]:
+ """ Render default managed auth page
+
+ Public HTML endpoint for the managed login page.
+ Requires `Accept: text/html`.
+
+ Args:
+ id (UUID):
+ action (RenderDefaultManagedAuthPageAction | Unset):
+ user_code (str | Unset):
+ anon_key (str | Unset):
+ state (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | str]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+action=action,
+user_code=user_code,
+anon_key=anon_key,
+state=state,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+ action: RenderDefaultManagedAuthPageAction | Unset = UNSET,
+ user_code: str | Unset = UNSET,
+ anon_key: str | Unset = UNSET,
+ state: str | Unset = UNSET,
+
+) -> Any | str | None:
+ """ Render default managed auth page
+
+ Public HTML endpoint for the managed login page.
+ Requires `Accept: text/html`.
+
+ Args:
+ id (UUID):
+ action (RenderDefaultManagedAuthPageAction | Unset):
+ user_code (str | Unset):
+ anon_key (str | Unset):
+ state (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | str
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+action=action,
+user_code=user_code,
+anon_key=anon_key,
+state=state,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/render_managed_auth_page.py b/src/volcano_sdk/_generated/api/auth_configuration/render_managed_auth_page.py
new file mode 100644
index 00000000..7c9a34e6
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/render_managed_auth_page.py
@@ -0,0 +1,207 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.hosted_renderable_page_type import check_hosted_renderable_page_type
+from ...models.hosted_renderable_page_type import HostedRenderablePageType
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ page_type: HostedRenderablePageType,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/auth/hosted/{page_type}".format(id=quote(str(id), safe=""),page_type=quote(str(page_type), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | str | None:
+ if response.status_code == 200:
+ response_200 = response.text
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | str]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ page_type: HostedRenderablePageType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Any | str]:
+ """ Render managed reset-password page
+
+ Public HTML endpoint for the managed reset-password page.
+ Requires `Accept: text/html`.
+ Returns 404 when managed hosted pages are disabled for the project.
+
+ Args:
+ id (UUID):
+ page_type (HostedRenderablePageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | str]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page_type=page_type,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ page_type: HostedRenderablePageType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Any | str | None:
+ """ Render managed reset-password page
+
+ Public HTML endpoint for the managed reset-password page.
+ Requires `Accept: text/html`.
+ Returns 404 when managed hosted pages are disabled for the project.
+
+ Args:
+ id (UUID):
+ page_type (HostedRenderablePageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | str
+ """
+
+
+ return sync_detailed(
+ id=id,
+page_type=page_type,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ page_type: HostedRenderablePageType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Any | str]:
+ """ Render managed reset-password page
+
+ Public HTML endpoint for the managed reset-password page.
+ Requires `Accept: text/html`.
+ Returns 404 when managed hosted pages are disabled for the project.
+
+ Args:
+ id (UUID):
+ page_type (HostedRenderablePageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | str]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page_type=page_type,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ page_type: HostedRenderablePageType,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Any | str | None:
+ """ Render managed reset-password page
+
+ Public HTML endpoint for the managed reset-password page.
+ Requires `Accept: text/html`.
+ Returns 404 when managed hosted pages are disabled for the project.
+
+ Args:
+ id (UUID):
+ page_type (HostedRenderablePageType):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | str
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+page_type=page_type,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/test_email_config.py b/src/volcano_sdk/_generated/api/auth_configuration/test_email_config.py
new file mode 100644
index 00000000..b725a1d7
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/test_email_config.py
@@ -0,0 +1,292 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.test_email_request import TestEmailRequest
+from ...models.test_email_response import TestEmailResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: TestEmailRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/auth/config/test-email".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | TestEmailResponse | None:
+ if response.status_code == 200:
+ response_200 = TestEmailResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if response.status_code == 502:
+ response_502 = cast(Any, None)
+ return response_502
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | TestEmailResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: TestEmailRequest,
+
+) -> Response[Any | TestEmailResponse]:
+ r""" Send a test email using the project's saved SMTP config
+
+ Sends a diagnostic email to `to_email` using the project's
+ persisted `auth_config` SMTP credentials. If `html_body` or
+ `text_body` is supplied, the override path is taken: those
+ values (plus optional `subject`) are rendered through
+ html/text templates against the project's `Data` and
+ used as the body — used by the template editor's \"Send Test\"
+ affordance to preview an unsaved template. With both bodies
+ omitted, a hardcoded diagnostic message is sent and any
+ `subject` field is ignored. Sending `subject` alone (no
+ bodies) is rejected with 400 to avoid a silently-dropped
+ subject or a blank message. Also rejects with 400 if
+ `email_enabled=false` or `smtp_host` is empty.
+
+ Args:
+ id (UUID):
+ body (TestEmailRequest): When `html_body` or `text_body` is provided the backend renders
+ those (plus optional `subject`) through html/text templates
+ against the standard `Data` (ProjectName, Name, SiteURL)
+ and sends the result — used by the template-editor "Send Test"
+ affordance to preview an unsaved template. When both bodies are
+ omitted a hardcoded diagnostic message is sent to verify SMTP
+ credentials and `subject` is ignored. Sending `subject` alone
+ (without a body) is rejected with 400.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | TestEmailResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: TestEmailRequest,
+
+) -> Any | TestEmailResponse | None:
+ r""" Send a test email using the project's saved SMTP config
+
+ Sends a diagnostic email to `to_email` using the project's
+ persisted `auth_config` SMTP credentials. If `html_body` or
+ `text_body` is supplied, the override path is taken: those
+ values (plus optional `subject`) are rendered through
+ html/text templates against the project's `Data` and
+ used as the body — used by the template editor's \"Send Test\"
+ affordance to preview an unsaved template. With both bodies
+ omitted, a hardcoded diagnostic message is sent and any
+ `subject` field is ignored. Sending `subject` alone (no
+ bodies) is rejected with 400 to avoid a silently-dropped
+ subject or a blank message. Also rejects with 400 if
+ `email_enabled=false` or `smtp_host` is empty.
+
+ Args:
+ id (UUID):
+ body (TestEmailRequest): When `html_body` or `text_body` is provided the backend renders
+ those (plus optional `subject`) through html/text templates
+ against the standard `Data` (ProjectName, Name, SiteURL)
+ and sends the result — used by the template-editor "Send Test"
+ affordance to preview an unsaved template. When both bodies are
+ omitted a hardcoded diagnostic message is sent to verify SMTP
+ credentials and `subject` is ignored. Sending `subject` alone
+ (without a body) is rejected with 400.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | TestEmailResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: TestEmailRequest,
+
+) -> Response[Any | TestEmailResponse]:
+ r""" Send a test email using the project's saved SMTP config
+
+ Sends a diagnostic email to `to_email` using the project's
+ persisted `auth_config` SMTP credentials. If `html_body` or
+ `text_body` is supplied, the override path is taken: those
+ values (plus optional `subject`) are rendered through
+ html/text templates against the project's `Data` and
+ used as the body — used by the template editor's \"Send Test\"
+ affordance to preview an unsaved template. With both bodies
+ omitted, a hardcoded diagnostic message is sent and any
+ `subject` field is ignored. Sending `subject` alone (no
+ bodies) is rejected with 400 to avoid a silently-dropped
+ subject or a blank message. Also rejects with 400 if
+ `email_enabled=false` or `smtp_host` is empty.
+
+ Args:
+ id (UUID):
+ body (TestEmailRequest): When `html_body` or `text_body` is provided the backend renders
+ those (plus optional `subject`) through html/text templates
+ against the standard `Data` (ProjectName, Name, SiteURL)
+ and sends the result — used by the template-editor "Send Test"
+ affordance to preview an unsaved template. When both bodies are
+ omitted a hardcoded diagnostic message is sent to verify SMTP
+ credentials and `subject` is ignored. Sending `subject` alone
+ (without a body) is rejected with 400.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | TestEmailResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: TestEmailRequest,
+
+) -> Any | TestEmailResponse | None:
+ r""" Send a test email using the project's saved SMTP config
+
+ Sends a diagnostic email to `to_email` using the project's
+ persisted `auth_config` SMTP credentials. If `html_body` or
+ `text_body` is supplied, the override path is taken: those
+ values (plus optional `subject`) are rendered through
+ html/text templates against the project's `Data` and
+ used as the body — used by the template editor's \"Send Test\"
+ affordance to preview an unsaved template. With both bodies
+ omitted, a hardcoded diagnostic message is sent and any
+ `subject` field is ignored. Sending `subject` alone (no
+ bodies) is rejected with 400 to avoid a silently-dropped
+ subject or a blank message. Also rejects with 400 if
+ `email_enabled=false` or `smtp_host` is empty.
+
+ Args:
+ id (UUID):
+ body (TestEmailRequest): When `html_body` or `text_body` is provided the backend renders
+ those (plus optional `subject`) through html/text templates
+ against the standard `Data` (ProjectName, Name, SiteURL)
+ and sends the result — used by the template-editor "Send Test"
+ affordance to preview an unsaved template. When both bodies are
+ omitted a hardcoded diagnostic message is sent to verify SMTP
+ credentials and `subject` is ignored. Sending `subject` alone
+ (without a body) is rejected with 400.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | TestEmailResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/update_auth_config.py b/src/volcano_sdk/_generated/api/auth_configuration/update_auth_config.py
new file mode 100644
index 00000000..965d7889
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/update_auth_config.py
@@ -0,0 +1,219 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_config import AuthConfig
+from ...models.error import Error
+from ...models.update_auth_config_request import UpdateAuthConfigRequest
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: UpdateAuthConfigRequest | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/auth/config".format(id=quote(str(id), safe=""),),
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthConfig | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthConfig.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthConfig | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthConfigRequest | Unset = UNSET,
+
+) -> Response[AuthConfig | Error]:
+ """ Update auth configuration
+
+ Updates the project's auth configuration. Only the fields present in
+ the body are changed.
+
+ Args:
+ id (UUID):
+ body (UpdateAuthConfigRequest | Unset): All fields optional - only include fields you want
+ to update. Validation rule: require_email_confirmation=true requires email_enabled=true.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthConfig | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthConfigRequest | Unset = UNSET,
+
+) -> AuthConfig | Error | None:
+ """ Update auth configuration
+
+ Updates the project's auth configuration. Only the fields present in
+ the body are changed.
+
+ Args:
+ id (UUID):
+ body (UpdateAuthConfigRequest | Unset): All fields optional - only include fields you want
+ to update. Validation rule: require_email_confirmation=true requires email_enabled=true.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthConfig | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthConfigRequest | Unset = UNSET,
+
+) -> Response[AuthConfig | Error]:
+ """ Update auth configuration
+
+ Updates the project's auth configuration. Only the fields present in
+ the body are changed.
+
+ Args:
+ id (UUID):
+ body (UpdateAuthConfigRequest | Unset): All fields optional - only include fields you want
+ to update. Validation rule: require_email_confirmation=true requires email_enabled=true.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthConfig | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthConfigRequest | Unset = UNSET,
+
+) -> AuthConfig | Error | None:
+ """ Update auth configuration
+
+ Updates the project's auth configuration. Only the fields present in
+ the body are changed.
+
+ Args:
+ id (UUID):
+ body (UpdateAuthConfigRequest | Unset): All fields optional - only include fields you want
+ to update. Validation rule: require_email_confirmation=true requires email_enabled=true.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthConfig | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/update_auth_hosted_page.py b/src/volcano_sdk/_generated/api/auth_configuration/update_auth_hosted_page.py
new file mode 100644
index 00000000..ec84956c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/update_auth_hosted_page.py
@@ -0,0 +1,243 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_hosted_page_response import AuthHostedPageResponse
+from ...models.hosted_auth_page_type import check_hosted_auth_page_type
+from ...models.hosted_auth_page_type import HostedAuthPageType
+from ...models.update_auth_hosted_page_request import UpdateAuthHostedPageRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ body: UpdateAuthHostedPageRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/auth/hosted-pages/{page_type}".format(id=quote(str(id), safe=""),page_type=quote(str(page_type), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthHostedPageResponse | None:
+ if response.status_code == 200:
+ response_200 = AuthHostedPageResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthHostedPageResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthHostedPageRequest,
+
+) -> Response[Any | AuthHostedPageResponse]:
+ """ Update hosted auth page
+
+ Saves the current HTML/CSS for this page type.
+ Security validation rejects script tags, javascript: URLs, inline event handlers,
+ iframe/object/embed/meta/link tags in HTML,
+ and closing style/head tags in CSS.
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+ body (UpdateAuthHostedPageRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthHostedPageResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page_type=page_type,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthHostedPageRequest,
+
+) -> Any | AuthHostedPageResponse | None:
+ """ Update hosted auth page
+
+ Saves the current HTML/CSS for this page type.
+ Security validation rejects script tags, javascript: URLs, inline event handlers,
+ iframe/object/embed/meta/link tags in HTML,
+ and closing style/head tags in CSS.
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+ body (UpdateAuthHostedPageRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthHostedPageResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+page_type=page_type,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthHostedPageRequest,
+
+) -> Response[Any | AuthHostedPageResponse]:
+ """ Update hosted auth page
+
+ Saves the current HTML/CSS for this page type.
+ Security validation rejects script tags, javascript: URLs, inline event handlers,
+ iframe/object/embed/meta/link tags in HTML,
+ and closing style/head tags in CSS.
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+ body (UpdateAuthHostedPageRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthHostedPageResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page_type=page_type,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ page_type: HostedAuthPageType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateAuthHostedPageRequest,
+
+) -> Any | AuthHostedPageResponse | None:
+ """ Update hosted auth page
+
+ Saves the current HTML/CSS for this page type.
+ Security validation rejects script tags, javascript: URLs, inline event handlers,
+ iframe/object/embed/meta/link tags in HTML,
+ and closing style/head tags in CSS.
+
+ Args:
+ id (UUID):
+ page_type (HostedAuthPageType):
+ body (UpdateAuthHostedPageRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthHostedPageResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+page_type=page_type,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/auth_configuration/update_email_template.py b/src/volcano_sdk/_generated/api/auth_configuration/update_email_template.py
new file mode 100644
index 00000000..5af6f517
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/auth_configuration/update_email_template.py
@@ -0,0 +1,239 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.email_template import EmailTemplate
+from ...models.error import Error
+from ...models.update_email_template_request import UpdateEmailTemplateRequest
+from ...models.update_email_template_type import check_update_email_template_type
+from ...models.update_email_template_type import UpdateEmailTemplateType
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ type_: UpdateEmailTemplateType,
+ *,
+ body: UpdateEmailTemplateRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/email-templates/{type_}".format(id=quote(str(id), safe=""),type_=quote(str(type_), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | EmailTemplate | Error | None:
+ if response.status_code == 200:
+ response_200 = EmailTemplate.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | EmailTemplate | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ type_: UpdateEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateEmailTemplateRequest,
+
+) -> Response[Any | EmailTemplate | Error]:
+ """ Update email template
+
+ Updates a custom email template. Custom email templates are a PRO-plan
+ feature: requests from a FREE-plan project owner are rejected with 403
+ (including after a PRO→FREE downgrade), so a FREE project cannot modify
+ templates and always sends the built-in defaults.
+
+ Args:
+ id (UUID):
+ type_ (UpdateEmailTemplateType):
+ body (UpdateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | EmailTemplate | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+type_=type_,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ type_: UpdateEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateEmailTemplateRequest,
+
+) -> Any | EmailTemplate | Error | None:
+ """ Update email template
+
+ Updates a custom email template. Custom email templates are a PRO-plan
+ feature: requests from a FREE-plan project owner are rejected with 403
+ (including after a PRO→FREE downgrade), so a FREE project cannot modify
+ templates and always sends the built-in defaults.
+
+ Args:
+ id (UUID):
+ type_ (UpdateEmailTemplateType):
+ body (UpdateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | EmailTemplate | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+type_=type_,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ type_: UpdateEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateEmailTemplateRequest,
+
+) -> Response[Any | EmailTemplate | Error]:
+ """ Update email template
+
+ Updates a custom email template. Custom email templates are a PRO-plan
+ feature: requests from a FREE-plan project owner are rejected with 403
+ (including after a PRO→FREE downgrade), so a FREE project cannot modify
+ templates and always sends the built-in defaults.
+
+ Args:
+ id (UUID):
+ type_ (UpdateEmailTemplateType):
+ body (UpdateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | EmailTemplate | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+type_=type_,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ type_: UpdateEmailTemplateType,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateEmailTemplateRequest,
+
+) -> Any | EmailTemplate | Error | None:
+ """ Update email template
+
+ Updates a custom email template. Custom email templates are a PRO-plan
+ feature: requests from a FREE-plan project owner are rejected with 403
+ (including after a PRO→FREE downgrade), so a FREE project cannot modify
+ templates and always sends the built-in defaults.
+
+ Args:
+ id (UUID):
+ type_ (UpdateEmailTemplateType):
+ body (UpdateEmailTemplateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | EmailTemplate | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+type_=type_,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/__init__.py b/src/volcano_sdk/_generated/api/authentication/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_cancel_email_change.py b/src/volcano_sdk/_generated/api/authentication/auth_cancel_email_change.py
new file mode 100644
index 00000000..6723967f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_cancel_email_change.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_cancel_email_change_response_200 import AuthCancelEmailChangeResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/auth/user/cancel-email-change",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthCancelEmailChangeResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthCancelEmailChangeResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthCancelEmailChangeResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthCancelEmailChangeResponse200 | Error]:
+ """ Cancel pending email change
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthCancelEmailChangeResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthCancelEmailChangeResponse200 | Error | None:
+ """ Cancel pending email change
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthCancelEmailChangeResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthCancelEmailChangeResponse200 | Error]:
+ """ Cancel pending email change
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthCancelEmailChangeResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthCancelEmailChangeResponse200 | Error | None:
+ """ Cancel pending email change
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthCancelEmailChangeResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_confirm_email.py b/src/volcano_sdk/_generated/api/authentication/auth_confirm_email.py
new file mode 100644
index 00000000..49e309cb
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_confirm_email.py
@@ -0,0 +1,198 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_confirm_email_body import AuthConfirmEmailBody
+from ...models.auth_confirm_email_response_200 import AuthConfirmEmailResponse200
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthConfirmEmailBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/confirm",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthConfirmEmailResponse200 | None:
+ if response.status_code == 200:
+ response_200 = AuthConfirmEmailResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthConfirmEmailResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailBody,
+
+) -> Response[Any | AuthConfirmEmailResponse200]:
+ """ Confirm email address
+
+ Confirm email address using token sent via email.
+ Required if require_email_confirmation is enabled.
+
+ Args:
+ body (AuthConfirmEmailBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthConfirmEmailResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailBody,
+
+) -> Any | AuthConfirmEmailResponse200 | None:
+ """ Confirm email address
+
+ Confirm email address using token sent via email.
+ Required if require_email_confirmation is enabled.
+
+ Args:
+ body (AuthConfirmEmailBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthConfirmEmailResponse200
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailBody,
+
+) -> Response[Any | AuthConfirmEmailResponse200]:
+ """ Confirm email address
+
+ Confirm email address using token sent via email.
+ Required if require_email_confirmation is enabled.
+
+ Args:
+ body (AuthConfirmEmailBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthConfirmEmailResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailBody,
+
+) -> Any | AuthConfirmEmailResponse200 | None:
+ """ Confirm email address
+
+ Confirm email address using token sent via email.
+ Required if require_email_confirmation is enabled.
+
+ Args:
+ body (AuthConfirmEmailBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthConfirmEmailResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_confirm_email_change.py b/src/volcano_sdk/_generated/api/authentication/auth_confirm_email_change.py
new file mode 100644
index 00000000..41277bf5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_confirm_email_change.py
@@ -0,0 +1,215 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_confirm_email_change_body import AuthConfirmEmailChangeBody
+from ...models.auth_confirm_email_change_response_200 import AuthConfirmEmailChangeResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthConfirmEmailChangeBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/user/confirm-email-change",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthConfirmEmailChangeResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthConfirmEmailChangeResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthConfirmEmailChangeResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailChangeBody,
+
+) -> Response[AuthConfirmEmailChangeResponse200 | Error]:
+ """ Confirm email change
+
+ Confirm email change with token sent to new address
+
+ Args:
+ body (AuthConfirmEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthConfirmEmailChangeResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailChangeBody,
+
+) -> AuthConfirmEmailChangeResponse200 | Error | None:
+ """ Confirm email change
+
+ Confirm email change with token sent to new address
+
+ Args:
+ body (AuthConfirmEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthConfirmEmailChangeResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailChangeBody,
+
+) -> Response[AuthConfirmEmailChangeResponse200 | Error]:
+ """ Confirm email change
+
+ Confirm email change with token sent to new address
+
+ Args:
+ body (AuthConfirmEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthConfirmEmailChangeResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConfirmEmailChangeBody,
+
+) -> AuthConfirmEmailChangeResponse200 | Error | None:
+ """ Confirm email change
+
+ Confirm email change with token sent to new address
+
+ Args:
+ body (AuthConfirmEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthConfirmEmailChangeResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_convert_anonymous.py b/src/volcano_sdk/_generated/api/authentication/auth_convert_anonymous.py
new file mode 100644
index 00000000..3c8480df
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_convert_anonymous.py
@@ -0,0 +1,222 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_convert_anonymous_body import AuthConvertAnonymousBody
+from ...models.auth_convert_anonymous_response_200 import AuthConvertAnonymousResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthConvertAnonymousBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/user/convert-anonymous",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthConvertAnonymousResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthConvertAnonymousResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = cast(Any, None)
+ return response_409
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthConvertAnonymousResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConvertAnonymousBody,
+
+) -> Response[Any | AuthConvertAnonymousResponse200 | Error]:
+ """ Convert anonymous user to authenticated
+
+ Add email and password to anonymous user.
+ Requires auth user access token.
+ If require_email_confirmation is enabled for the project, the converted
+ user remains unconfirmed until /auth/confirm succeeds. When email
+ sending is enabled, a confirmation email is sent during conversion.
+
+ Args:
+ body (AuthConvertAnonymousBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthConvertAnonymousResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConvertAnonymousBody,
+
+) -> Any | AuthConvertAnonymousResponse200 | Error | None:
+ """ Convert anonymous user to authenticated
+
+ Add email and password to anonymous user.
+ Requires auth user access token.
+ If require_email_confirmation is enabled for the project, the converted
+ user remains unconfirmed until /auth/confirm succeeds. When email
+ sending is enabled, a confirmation email is sent during conversion.
+
+ Args:
+ body (AuthConvertAnonymousBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthConvertAnonymousResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConvertAnonymousBody,
+
+) -> Response[Any | AuthConvertAnonymousResponse200 | Error]:
+ """ Convert anonymous user to authenticated
+
+ Add email and password to anonymous user.
+ Requires auth user access token.
+ If require_email_confirmation is enabled for the project, the converted
+ user remains unconfirmed until /auth/confirm succeeds. When email
+ sending is enabled, a confirmation email is sent during conversion.
+
+ Args:
+ body (AuthConvertAnonymousBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthConvertAnonymousResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthConvertAnonymousBody,
+
+) -> Any | AuthConvertAnonymousResponse200 | Error | None:
+ """ Convert anonymous user to authenticated
+
+ Add email and password to anonymous user.
+ Requires auth user access token.
+ If require_email_confirmation is enabled for the project, the converted
+ user remains unconfirmed until /auth/confirm succeeds. When email
+ sending is enabled, a confirmation email is sent during conversion.
+
+ Args:
+ body (AuthConvertAnonymousBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthConvertAnonymousResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_delete_all_my_sessions.py b/src/volcano_sdk/_generated/api/authentication/auth_delete_all_my_sessions.py
new file mode 100644
index 00000000..c3bf3283
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_delete_all_my_sessions.py
@@ -0,0 +1,166 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/auth/user/sessions",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Sign out from all other devices
+
+ Deletes all sessions except the current one.
+ Use this to log out from all other devices while keeping the current session active.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Sign out from all other devices
+
+ Deletes all sessions except the current one.
+ Use this to log out from all other devices while keeping the current session active.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Sign out from all other devices
+
+ Deletes all sessions except the current one.
+ Use this to log out from all other devices while keeping the current session active.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Sign out from all other devices
+
+ Deletes all sessions except the current one.
+ Use this to log out from all other devices while keeping the current session active.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_delete_my_session.py b/src/volcano_sdk/_generated/api/authentication/auth_delete_my_session.py
new file mode 100644
index 00000000..cfb4cade
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_delete_my_session.py
@@ -0,0 +1,195 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ session_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/auth/user/sessions/{session_id}".format(session_id=quote(str(session_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ session_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Sign out from specific device
+
+ Deletes a specific session, logging out that device.
+ You can get session IDs from the list sessions endpoint.
+
+ Args:
+ session_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ session_id=session_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ session_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Sign out from specific device
+
+ Deletes a specific session, logging out that device.
+ You can get session IDs from the list sessions endpoint.
+
+ Args:
+ session_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ session_id=session_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ session_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Sign out from specific device
+
+ Deletes a specific session, logging out that device.
+ You can get session IDs from the list sessions endpoint.
+
+ Args:
+ session_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ session_id=session_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ session_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Sign out from specific device
+
+ Deletes a specific session, logging out that device.
+ You can get session IDs from the list sessions endpoint.
+
+ Args:
+ session_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ session_id=session_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_forgot_password.py b/src/volcano_sdk/_generated/api/authentication/auth_forgot_password.py
new file mode 100644
index 00000000..67b92232
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_forgot_password.py
@@ -0,0 +1,209 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_forgot_password_body import AuthForgotPasswordBody
+from ...models.auth_forgot_password_response_200 import AuthForgotPasswordResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthForgotPasswordBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/forgot-password",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthForgotPasswordResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthForgotPasswordResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthForgotPasswordResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthForgotPasswordBody,
+
+) -> Response[AuthForgotPasswordResponse200 | Error]:
+ """ Request password reset
+
+ Generates recovery token and stores it (email sending pending).
+ Returns generic message to prevent email enumeration.
+ Project is identified via the anon key.
+
+ Args:
+ body (AuthForgotPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthForgotPasswordResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthForgotPasswordBody,
+
+) -> AuthForgotPasswordResponse200 | Error | None:
+ """ Request password reset
+
+ Generates recovery token and stores it (email sending pending).
+ Returns generic message to prevent email enumeration.
+ Project is identified via the anon key.
+
+ Args:
+ body (AuthForgotPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthForgotPasswordResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthForgotPasswordBody,
+
+) -> Response[AuthForgotPasswordResponse200 | Error]:
+ """ Request password reset
+
+ Generates recovery token and stores it (email sending pending).
+ Returns generic message to prevent email enumeration.
+ Project is identified via the anon key.
+
+ Args:
+ body (AuthForgotPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthForgotPasswordResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthForgotPasswordBody,
+
+) -> AuthForgotPasswordResponse200 | Error | None:
+ """ Request password reset
+
+ Generates recovery token and stores it (email sending pending).
+ Returns generic message to prevent email enumeration.
+ Project is identified via the anon key.
+
+ Args:
+ body (AuthForgotPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthForgotPasswordResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_get_my_sessions.py b/src/volcano_sdk/_generated/api/authentication/auth_get_my_sessions.py
new file mode 100644
index 00000000..87c38e4c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_get_my_sessions.py
@@ -0,0 +1,397 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_get_my_sessions_response_200 import AuthGetMySessionsResponse200
+from ...models.auth_get_my_sessions_sort import AuthGetMySessionsSort
+from ...models.auth_get_my_sessions_sort import check_auth_get_my_sessions_sort
+from ...models.auth_get_my_sessions_status import AuthGetMySessionsStatus
+from ...models.auth_get_my_sessions_status import check_auth_get_my_sessions_status
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: AuthGetMySessionsSort | Unset = 'last_activity',
+ status: AuthGetMySessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ json_sort: str | Unset = UNSET
+ if not isinstance(sort, Unset):
+ json_sort = sort
+
+ params["sort"] = json_sort
+
+ json_status: str | Unset = UNSET
+ if not isinstance(status, Unset):
+ json_status = status
+
+ params["status"] = json_status
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/user/sessions",
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthGetMySessionsResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthGetMySessionsResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthGetMySessionsResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: AuthGetMySessionsSort | Unset = 'last_activity',
+ status: AuthGetMySessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> Response[AuthGetMySessionsResponse200 | Error]:
+ """ Get current user's sessions
+
+ Returns paginated sessions for the currently authenticated user.
+ Each session includes device info, IP addresses, and activity timestamps.
+ The current session is marked with `is_current: true`.
+
+ **Ordering and pagination.** Without `sort`, results are ordered by most
+ recent activity and paged with `page`/`limit`, returning the
+ `sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the
+ legacy default and is preserved for existing clients.
+
+ Send `sort=created_at` to opt into the standard list contract: results are
+ ordered by session start (newest first) and may be paged either with
+ `page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded
+ `offset` past the cursor anchor. Cursor responses use the shared
+ `data` envelope with `next_cursor`/`prev_cursor`.
+
+ Unlike other list endpoints, sending `limit` without `page` does **not**
+ select cursor mode here; `sort=created_at` is the only opt-in. Cursor
+ pagination is rejected with 400 for the activity order, because
+ `last_activity_at` changes whenever a session refreshes its token: a row
+ that crosses the cursor anchor between two requests would be skipped and
+ never shown. The `status=expired` filter is also offset-only because a
+ session can expire above the cursor anchor during a walk. Sending that
+ filter in cursor mode, `page` with `cursor` or `ending_before`, or both
+ cursor directions returns 400.
+
+ Args:
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (AuthGetMySessionsSort | Unset): Default: 'last_activity'.
+ status (AuthGetMySessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthGetMySessionsResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: AuthGetMySessionsSort | Unset = 'last_activity',
+ status: AuthGetMySessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> AuthGetMySessionsResponse200 | Error | None:
+ """ Get current user's sessions
+
+ Returns paginated sessions for the currently authenticated user.
+ Each session includes device info, IP addresses, and activity timestamps.
+ The current session is marked with `is_current: true`.
+
+ **Ordering and pagination.** Without `sort`, results are ordered by most
+ recent activity and paged with `page`/`limit`, returning the
+ `sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the
+ legacy default and is preserved for existing clients.
+
+ Send `sort=created_at` to opt into the standard list contract: results are
+ ordered by session start (newest first) and may be paged either with
+ `page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded
+ `offset` past the cursor anchor. Cursor responses use the shared
+ `data` envelope with `next_cursor`/`prev_cursor`.
+
+ Unlike other list endpoints, sending `limit` without `page` does **not**
+ select cursor mode here; `sort=created_at` is the only opt-in. Cursor
+ pagination is rejected with 400 for the activity order, because
+ `last_activity_at` changes whenever a session refreshes its token: a row
+ that crosses the cursor anchor between two requests would be skipped and
+ never shown. The `status=expired` filter is also offset-only because a
+ session can expire above the cursor anchor during a walk. Sending that
+ filter in cursor mode, `page` with `cursor` or `ending_before`, or both
+ cursor directions returns 400.
+
+ Args:
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (AuthGetMySessionsSort | Unset): Default: 'last_activity'.
+ status (AuthGetMySessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthGetMySessionsResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: AuthGetMySessionsSort | Unset = 'last_activity',
+ status: AuthGetMySessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> Response[AuthGetMySessionsResponse200 | Error]:
+ """ Get current user's sessions
+
+ Returns paginated sessions for the currently authenticated user.
+ Each session includes device info, IP addresses, and activity timestamps.
+ The current session is marked with `is_current: true`.
+
+ **Ordering and pagination.** Without `sort`, results are ordered by most
+ recent activity and paged with `page`/`limit`, returning the
+ `sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the
+ legacy default and is preserved for existing clients.
+
+ Send `sort=created_at` to opt into the standard list contract: results are
+ ordered by session start (newest first) and may be paged either with
+ `page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded
+ `offset` past the cursor anchor. Cursor responses use the shared
+ `data` envelope with `next_cursor`/`prev_cursor`.
+
+ Unlike other list endpoints, sending `limit` without `page` does **not**
+ select cursor mode here; `sort=created_at` is the only opt-in. Cursor
+ pagination is rejected with 400 for the activity order, because
+ `last_activity_at` changes whenever a session refreshes its token: a row
+ that crosses the cursor anchor between two requests would be skipped and
+ never shown. The `status=expired` filter is also offset-only because a
+ session can expire above the cursor anchor during a walk. Sending that
+ filter in cursor mode, `page` with `cursor` or `ending_before`, or both
+ cursor directions returns 400.
+
+ Args:
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (AuthGetMySessionsSort | Unset): Default: 'last_activity'.
+ status (AuthGetMySessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthGetMySessionsResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = 1,
+ limit: int | Unset = 20,
+ sort: AuthGetMySessionsSort | Unset = 'last_activity',
+ status: AuthGetMySessionsStatus | Unset = UNSET,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = UNSET,
+
+) -> AuthGetMySessionsResponse200 | Error | None:
+ """ Get current user's sessions
+
+ Returns paginated sessions for the currently authenticated user.
+ Each session includes device info, IP addresses, and activity timestamps.
+ The current session is marked with `is_current: true`.
+
+ **Ordering and pagination.** Without `sort`, results are ordered by most
+ recent activity and paged with `page`/`limit`, returning the
+ `sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the
+ legacy default and is preserved for existing clients.
+
+ Send `sort=created_at` to opt into the standard list contract: results are
+ ordered by session start (newest first) and may be paged either with
+ `page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded
+ `offset` past the cursor anchor. Cursor responses use the shared
+ `data` envelope with `next_cursor`/`prev_cursor`.
+
+ Unlike other list endpoints, sending `limit` without `page` does **not**
+ select cursor mode here; `sort=created_at` is the only opt-in. Cursor
+ pagination is rejected with 400 for the activity order, because
+ `last_activity_at` changes whenever a session refreshes its token: a row
+ that crosses the cursor anchor between two requests would be skipped and
+ never shown. The `status=expired` filter is also offset-only because a
+ session can expire above the cursor anchor during a walk. Sending that
+ filter in cursor mode, `page` with `cursor` or `ending_before`, or both
+ cursor directions returns 400.
+
+ Args:
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 20.
+ sort (AuthGetMySessionsSort | Unset): Default: 'last_activity'.
+ status (AuthGetMySessionsStatus | Unset):
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthGetMySessionsResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+page=page,
+limit=limit,
+sort=sort,
+status=status,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_get_password_policy.py b/src/volcano_sdk/_generated/api/authentication/auth_get_password_policy.py
new file mode 100644
index 00000000..e7e75f5e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_get_password_policy.py
@@ -0,0 +1,181 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_password_policy import AuthPasswordPolicy
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/password-policy",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthPasswordPolicy | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthPasswordPolicy.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthPasswordPolicy | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthPasswordPolicy | Error]:
+ """ Get the effective password policy
+
+ Returns the backend-enforced password bounds and compromised-password
+ screening status for the project identified by the anon key. A valid
+ anon key is required, but no route-specific auth permission is needed.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthPasswordPolicy | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthPasswordPolicy | Error | None:
+ """ Get the effective password policy
+
+ Returns the backend-enforced password bounds and compromised-password
+ screening status for the project identified by the anon key. A valid
+ anon key is required, but no route-specific auth permission is needed.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthPasswordPolicy | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthPasswordPolicy | Error]:
+ """ Get the effective password policy
+
+ Returns the backend-enforced password bounds and compromised-password
+ screening status for the project identified by the anon key. A valid
+ anon key is required, but no route-specific auth permission is needed.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthPasswordPolicy | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthPasswordPolicy | Error | None:
+ """ Get the effective password policy
+
+ Returns the backend-enforced password bounds and compromised-password
+ screening status for the project identified by the anon key. A valid
+ anon key is required, but no route-specific auth permission is needed.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthPasswordPolicy | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_get_user.py b/src/volcano_sdk/_generated/api/authentication/auth_get_user.py
new file mode 100644
index 00000000..4526ee43
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_get_user.py
@@ -0,0 +1,166 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_get_user_response_200 import AuthGetUserResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/user",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthGetUserResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthGetUserResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthGetUserResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthGetUserResponse200 | Error]:
+ """ Get current user profile
+
+ Returns authenticated user's profile. Requires access token.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthGetUserResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthGetUserResponse200 | Error | None:
+ """ Get current user profile
+
+ Returns authenticated user's profile. Requires access token.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthGetUserResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthGetUserResponse200 | Error]:
+ """ Get current user profile
+
+ Returns authenticated user's profile. Requires access token.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthGetUserResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthGetUserResponse200 | Error | None:
+ """ Get current user profile
+
+ Returns authenticated user's profile. Requires access token.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthGetUserResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_list_identities.py b/src/volcano_sdk/_generated/api/authentication/auth_list_identities.py
new file mode 100644
index 00000000..46274893
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_list_identities.py
@@ -0,0 +1,178 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_identities_response import AuthIdentitiesResponse
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/user/identities",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthIdentitiesResponse | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthIdentitiesResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthIdentitiesResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthIdentitiesResponse | Error]:
+ """ List the current user's identities
+
+ Returns every real email identity the account owns. An account can own
+ multiple identities (for example a password identity plus one or more
+ OAuth identities on different emails). Anonymous accounts have no real
+ identity and return an empty list.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthIdentitiesResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthIdentitiesResponse | Error | None:
+ """ List the current user's identities
+
+ Returns every real email identity the account owns. An account can own
+ multiple identities (for example a password identity plus one or more
+ OAuth identities on different emails). Anonymous accounts have no real
+ identity and return an empty list.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthIdentitiesResponse | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthIdentitiesResponse | Error]:
+ """ List the current user's identities
+
+ Returns every real email identity the account owns. An account can own
+ multiple identities (for example a password identity plus one or more
+ OAuth identities on different emails). Anonymous accounts have no real
+ identity and return an empty list.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthIdentitiesResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthIdentitiesResponse | Error | None:
+ """ List the current user's identities
+
+ Returns every real email identity the account owns. An account can own
+ multiple identities (for example a password identity plus one or more
+ OAuth identities on different emails). Anonymous accounts have no real
+ identity and return an empty list.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthIdentitiesResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_list_methods.py b/src/volcano_sdk/_generated/api/authentication/auth_list_methods.py
new file mode 100644
index 00000000..bb98a791
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_list_methods.py
@@ -0,0 +1,174 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_methods_response import AuthMethodsResponse
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/user/methods",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthMethodsResponse | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthMethodsResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthMethodsResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthMethodsResponse | Error]:
+ """ List the current user's sign-in methods
+
+ Returns a flat list of every sign-in method the account owns (password,
+ each OAuth provider, and any active anonymous method), with the primary
+ method flagged. Password stubs and converted anonymous methods are excluded.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthMethodsResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthMethodsResponse | Error | None:
+ """ List the current user's sign-in methods
+
+ Returns a flat list of every sign-in method the account owns (password,
+ each OAuth provider, and any active anonymous method), with the primary
+ method flagged. Password stubs and converted anonymous methods are excluded.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthMethodsResponse | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthMethodsResponse | Error]:
+ """ List the current user's sign-in methods
+
+ Returns a flat list of every sign-in method the account owns (password,
+ each OAuth provider, and any active anonymous method), with the primary
+ method flagged. Password stubs and converted anonymous methods are excluded.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthMethodsResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthMethodsResponse | Error | None:
+ """ List the current user's sign-in methods
+
+ Returns a flat list of every sign-in method the account owns (password,
+ each OAuth provider, and any active anonymous method), with the primary
+ method flagged. Password stubs and converted anonymous methods are excluded.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthMethodsResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_logout.py b/src/volcano_sdk/_generated/api/authentication/auth_logout.py
new file mode 100644
index 00000000..a2fc7bba
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_logout.py
@@ -0,0 +1,138 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_logout_body import AuthLogoutBody
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthLogoutBody | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/logout",
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 204:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthLogoutBody | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Logout (revoke refresh token)
+
+ Invalidate a refresh token. Requires an anon key.
+
+ Send `refresh_token` for the default flow. An eligible cookie-mode
+ browser request may instead send `session_mode: cookie` with an empty
+ token; logout remains idempotent when the cookie is missing or expired.
+
+ Args:
+ body (AuthLogoutBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthLogoutBody | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Logout (revoke refresh token)
+
+ Invalidate a refresh token. Requires an anon key.
+
+ Send `refresh_token` for the default flow. An eligible cookie-mode
+ browser request may instead send `session_mode: cookie` with an empty
+ token; logout remains idempotent when the cookie is missing or expired.
+
+ Args:
+ body (AuthLogoutBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_promote_method.py b/src/volcano_sdk/_generated/api/authentication/auth_promote_method.py
new file mode 100644
index 00000000..eeaf7cd5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_promote_method.py
@@ -0,0 +1,221 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_method_summary import AuthMethodSummary
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ method_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/user/methods/{method_id}/promote".format(method_id=quote(str(method_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthMethodSummary | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthMethodSummary.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthMethodSummary | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ method_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthMethodSummary | Error]:
+ """ Set a method as the account's primary
+
+ Promotes the given method to the account's primary sign-in method. The
+ account's canonical email is re-derived from the promoted method's identity.
+ Refused for password stubs and converted anonymous methods, and for an
+ identity whose domain is outside the project's `allowed_email_domains`.
+
+ Args:
+ method_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthMethodSummary | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ method_id=method_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ method_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthMethodSummary | Error | None:
+ """ Set a method as the account's primary
+
+ Promotes the given method to the account's primary sign-in method. The
+ account's canonical email is re-derived from the promoted method's identity.
+ Refused for password stubs and converted anonymous methods, and for an
+ identity whose domain is outside the project's `allowed_email_domains`.
+
+ Args:
+ method_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthMethodSummary | Error
+ """
+
+
+ return sync_detailed(
+ method_id=method_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ method_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthMethodSummary | Error]:
+ """ Set a method as the account's primary
+
+ Promotes the given method to the account's primary sign-in method. The
+ account's canonical email is re-derived from the promoted method's identity.
+ Refused for password stubs and converted anonymous methods, and for an
+ identity whose domain is outside the project's `allowed_email_domains`.
+
+ Args:
+ method_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthMethodSummary | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ method_id=method_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ method_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthMethodSummary | Error | None:
+ """ Set a method as the account's primary
+
+ Promotes the given method to the account's primary sign-in method. The
+ account's canonical email is re-derived from the promoted method's identity.
+ Refused for password stubs and converted anonymous methods, and for an
+ identity whose domain is outside the project's `allowed_email_domains`.
+
+ Args:
+ method_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthMethodSummary | Error
+ """
+
+
+ return (await asyncio_detailed(
+ method_id=method_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_refresh.py b/src/volcano_sdk/_generated/api/authentication/auth_refresh.py
new file mode 100644
index 00000000..3c4a2a25
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_refresh.py
@@ -0,0 +1,235 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_refresh_body import AuthRefreshBody
+from ...models.auth_token_response import AuthTokenResponse
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthRefreshBody | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/refresh",
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthTokenResponse | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthTokenResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthTokenResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRefreshBody | Unset = UNSET,
+
+) -> Response[AuthTokenResponse | Error]:
+ """ Refresh access token
+
+ Get a new access token using a refresh token. Requires an anon key.
+
+ Send `refresh_token` in the body for the default flow. An eligible
+ cookie-mode browser request may instead send `session_mode: cookie`
+ with an empty token or omit the request body; the API reads and resets
+ the project's HttpOnly cookie and omits `refresh_token` from the
+ response.
+
+ Args:
+ body (AuthRefreshBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthTokenResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRefreshBody | Unset = UNSET,
+
+) -> AuthTokenResponse | Error | None:
+ """ Refresh access token
+
+ Get a new access token using a refresh token. Requires an anon key.
+
+ Send `refresh_token` in the body for the default flow. An eligible
+ cookie-mode browser request may instead send `session_mode: cookie`
+ with an empty token or omit the request body; the API reads and resets
+ the project's HttpOnly cookie and omits `refresh_token` from the
+ response.
+
+ Args:
+ body (AuthRefreshBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthTokenResponse | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRefreshBody | Unset = UNSET,
+
+) -> Response[AuthTokenResponse | Error]:
+ """ Refresh access token
+
+ Get a new access token using a refresh token. Requires an anon key.
+
+ Send `refresh_token` in the body for the default flow. An eligible
+ cookie-mode browser request may instead send `session_mode: cookie`
+ with an empty token or omit the request body; the API reads and resets
+ the project's HttpOnly cookie and omits `refresh_token` from the
+ response.
+
+ Args:
+ body (AuthRefreshBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthTokenResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRefreshBody | Unset = UNSET,
+
+) -> AuthTokenResponse | Error | None:
+ """ Refresh access token
+
+ Get a new access token using a refresh token. Requires an anon key.
+
+ Send `refresh_token` in the body for the default flow. An eligible
+ cookie-mode browser request may instead send `session_mode: cookie`
+ with an empty token or omit the request body; the API reads and resets
+ the project's HttpOnly cookie and omits `refresh_token` from the
+ response.
+
+ Args:
+ body (AuthRefreshBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthTokenResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_request_email_change.py b/src/volcano_sdk/_generated/api/authentication/auth_request_email_change.py
new file mode 100644
index 00000000..d3f23ed8
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_request_email_change.py
@@ -0,0 +1,226 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_request_email_change_body import AuthRequestEmailChangeBody
+from ...models.auth_request_email_change_response_200 import AuthRequestEmailChangeResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthRequestEmailChangeBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/user/change-email",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthRequestEmailChangeResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthRequestEmailChangeResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthRequestEmailChangeResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRequestEmailChangeBody,
+
+) -> Response[AuthRequestEmailChangeResponse200 | Error]:
+ """ Request email change
+
+ Request to change user's email address.
+ Sends confirmation token to new email address.
+
+ Args:
+ body (AuthRequestEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthRequestEmailChangeResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRequestEmailChangeBody,
+
+) -> AuthRequestEmailChangeResponse200 | Error | None:
+ """ Request email change
+
+ Request to change user's email address.
+ Sends confirmation token to new email address.
+
+ Args:
+ body (AuthRequestEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthRequestEmailChangeResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRequestEmailChangeBody,
+
+) -> Response[AuthRequestEmailChangeResponse200 | Error]:
+ """ Request email change
+
+ Request to change user's email address.
+ Sends confirmation token to new email address.
+
+ Args:
+ body (AuthRequestEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthRequestEmailChangeResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthRequestEmailChangeBody,
+
+) -> AuthRequestEmailChangeResponse200 | Error | None:
+ """ Request email change
+
+ Request to change user's email address.
+ Sends confirmation token to new email address.
+
+ Args:
+ body (AuthRequestEmailChangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthRequestEmailChangeResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_resend_confirmation.py b/src/volcano_sdk/_generated/api/authentication/auth_resend_confirmation.py
new file mode 100644
index 00000000..489ddb47
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_resend_confirmation.py
@@ -0,0 +1,210 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_resend_confirmation_body import AuthResendConfirmationBody
+from ...models.auth_resend_confirmation_response_200 import AuthResendConfirmationResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthResendConfirmationBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/resend-confirmation",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthResendConfirmationResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthResendConfirmationResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthResendConfirmationResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResendConfirmationBody,
+
+) -> Response[AuthResendConfirmationResponse200 | Error]:
+ """ Resend confirmation email
+
+ Resend email confirmation link.
+ Returns generic message to prevent email enumeration.
+ No email is sent when the account does not exist or is already confirmed.
+ If the account exists and is unconfirmed, a new token is generated and
+ any previous confirmation token is invalidated.
+
+ Args:
+ body (AuthResendConfirmationBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthResendConfirmationResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResendConfirmationBody,
+
+) -> AuthResendConfirmationResponse200 | Error | None:
+ """ Resend confirmation email
+
+ Resend email confirmation link.
+ Returns generic message to prevent email enumeration.
+ No email is sent when the account does not exist or is already confirmed.
+ If the account exists and is unconfirmed, a new token is generated and
+ any previous confirmation token is invalidated.
+
+ Args:
+ body (AuthResendConfirmationBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthResendConfirmationResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResendConfirmationBody,
+
+) -> Response[AuthResendConfirmationResponse200 | Error]:
+ """ Resend confirmation email
+
+ Resend email confirmation link.
+ Returns generic message to prevent email enumeration.
+ No email is sent when the account does not exist or is already confirmed.
+ If the account exists and is unconfirmed, a new token is generated and
+ any previous confirmation token is invalidated.
+
+ Args:
+ body (AuthResendConfirmationBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthResendConfirmationResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResendConfirmationBody,
+
+) -> AuthResendConfirmationResponse200 | Error | None:
+ """ Resend confirmation email
+
+ Resend email confirmation link.
+ Returns generic message to prevent email enumeration.
+ No email is sent when the account does not exist or is already confirmed.
+ If the account exists and is unconfirmed, a new token is generated and
+ any previous confirmation token is invalidated.
+
+ Args:
+ body (AuthResendConfirmationBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthResendConfirmationResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_reset_password.py b/src/volcano_sdk/_generated/api/authentication/auth_reset_password.py
new file mode 100644
index 00000000..567c82fe
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_reset_password.py
@@ -0,0 +1,206 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_reset_password_body import AuthResetPasswordBody
+from ...models.auth_reset_password_response_200 import AuthResetPasswordResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthResetPasswordBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/reset-password",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthResetPasswordResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthResetPasswordResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthResetPasswordResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResetPasswordBody,
+
+) -> Response[Any | AuthResetPasswordResponse200 | Error]:
+ """ Reset password with recovery token
+
+ Reset password using recovery token from forgot-password.
+ Revokes all existing sessions for security.
+
+ Args:
+ body (AuthResetPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthResetPasswordResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResetPasswordBody,
+
+) -> Any | AuthResetPasswordResponse200 | Error | None:
+ """ Reset password with recovery token
+
+ Reset password using recovery token from forgot-password.
+ Revokes all existing sessions for security.
+
+ Args:
+ body (AuthResetPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthResetPasswordResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResetPasswordBody,
+
+) -> Response[Any | AuthResetPasswordResponse200 | Error]:
+ """ Reset password with recovery token
+
+ Reset password using recovery token from forgot-password.
+ Revokes all existing sessions for security.
+
+ Args:
+ body (AuthResetPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthResetPasswordResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthResetPasswordBody,
+
+) -> Any | AuthResetPasswordResponse200 | Error | None:
+ """ Reset password with recovery token
+
+ Reset password using recovery token from forgot-password.
+ Revokes all existing sessions for security.
+
+ Args:
+ body (AuthResetPasswordBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthResetPasswordResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_signin.py b/src/volcano_sdk/_generated/api/authentication/auth_signin.py
new file mode 100644
index 00000000..3eca7291
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_signin.py
@@ -0,0 +1,222 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_signin_body import AuthSigninBody
+from ...models.auth_token_response import AuthTokenResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthSigninBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/signin",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthTokenResponse | None:
+ if response.status_code == 200:
+ response_200 = AuthTokenResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = cast(Any, None)
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthTokenResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSigninBody,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ Sign in an auth user
+
+ Authenticate with email and password. Requires an anon key.
+
+ Set `session_mode` to `cookie` to request HttpOnly refresh-token
+ storage. Cookie mode is honored only for an exact, credentialed CORS
+ origin on the same schemeful site as this API. Otherwise the response
+ retains the refresh token in its body.
+
+ Args:
+ body (AuthSigninBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSigninBody,
+
+) -> Any | AuthTokenResponse | None:
+ """ Sign in an auth user
+
+ Authenticate with email and password. Requires an anon key.
+
+ Set `session_mode` to `cookie` to request HttpOnly refresh-token
+ storage. Cookie mode is honored only for an exact, credentialed CORS
+ origin on the same schemeful site as this API. Otherwise the response
+ retains the refresh token in its body.
+
+ Args:
+ body (AuthSigninBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSigninBody,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ Sign in an auth user
+
+ Authenticate with email and password. Requires an anon key.
+
+ Set `session_mode` to `cookie` to request HttpOnly refresh-token
+ storage. Cookie mode is honored only for an exact, credentialed CORS
+ origin on the same schemeful site as this API. Otherwise the response
+ retains the refresh token in its body.
+
+ Args:
+ body (AuthSigninBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSigninBody,
+
+) -> Any | AuthTokenResponse | None:
+ """ Sign in an auth user
+
+ Authenticate with email and password. Requires an anon key.
+
+ Set `session_mode` to `cookie` to request HttpOnly refresh-token
+ storage. Cookie mode is honored only for an exact, credentialed CORS
+ origin on the same schemeful site as this API. Otherwise the response
+ retains the refresh token in its body.
+
+ Args:
+ body (AuthSigninBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_signup.py b/src/volcano_sdk/_generated/api/authentication/auth_signup.py
new file mode 100644
index 00000000..61936734
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_signup.py
@@ -0,0 +1,254 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_signup_body import AuthSignupBody
+from ...models.auth_signup_response import AuthSignupResponse
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthSignupBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/signup",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthSignupResponse | Error | None:
+ if response.status_code == 201:
+ response_201 = AuthSignupResponse.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = cast(Any, None)
+ return response_429
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthSignupResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupBody,
+
+) -> Response[Any | AuthSignupResponse | Error]:
+ """ Sign up a new auth user
+
+ Create a new end-user account. The project is determined from the anon key.
+ Requires project-specific anon key in Authorization header.
+
+ **Session-less**: signup never issues a session. On success it returns a
+ uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client
+ obtains a session with a subsequent `POST /auth/signin`. If email confirmation
+ is enabled for the project, a confirmation email is sent and
+ `confirmation_required` is `true`.
+
+ **Anti-enumeration**: a signup for an already-registered email returns the
+ exact same `201` response as a fresh signup — it never returns `409` — so the
+ response cannot be used to discover which emails are registered.
+
+ Args:
+ body (AuthSignupBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthSignupResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupBody,
+
+) -> Any | AuthSignupResponse | Error | None:
+ """ Sign up a new auth user
+
+ Create a new end-user account. The project is determined from the anon key.
+ Requires project-specific anon key in Authorization header.
+
+ **Session-less**: signup never issues a session. On success it returns a
+ uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client
+ obtains a session with a subsequent `POST /auth/signin`. If email confirmation
+ is enabled for the project, a confirmation email is sent and
+ `confirmation_required` is `true`.
+
+ **Anti-enumeration**: a signup for an already-registered email returns the
+ exact same `201` response as a fresh signup — it never returns `409` — so the
+ response cannot be used to discover which emails are registered.
+
+ Args:
+ body (AuthSignupBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthSignupResponse | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupBody,
+
+) -> Response[Any | AuthSignupResponse | Error]:
+ """ Sign up a new auth user
+
+ Create a new end-user account. The project is determined from the anon key.
+ Requires project-specific anon key in Authorization header.
+
+ **Session-less**: signup never issues a session. On success it returns a
+ uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client
+ obtains a session with a subsequent `POST /auth/signin`. If email confirmation
+ is enabled for the project, a confirmation email is sent and
+ `confirmation_required` is `true`.
+
+ **Anti-enumeration**: a signup for an already-registered email returns the
+ exact same `201` response as a fresh signup — it never returns `409` — so the
+ response cannot be used to discover which emails are registered.
+
+ Args:
+ body (AuthSignupBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthSignupResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupBody,
+
+) -> Any | AuthSignupResponse | Error | None:
+ """ Sign up a new auth user
+
+ Create a new end-user account. The project is determined from the anon key.
+ Requires project-specific anon key in Authorization header.
+
+ **Session-less**: signup never issues a session. On success it returns a
+ uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client
+ obtains a session with a subsequent `POST /auth/signin`. If email confirmation
+ is enabled for the project, a confirmation email is sent and
+ `confirmation_required` is `true`.
+
+ **Anti-enumeration**: a signup for an already-registered email returns the
+ exact same `201` response as a fresh signup — it never returns `409` — so the
+ response cannot be used to discover which emails are registered.
+
+ Args:
+ body (AuthSignupBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthSignupResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_signup_anonymous.py b/src/volcano_sdk/_generated/api/authentication/auth_signup_anonymous.py
new file mode 100644
index 00000000..922e28a1
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_signup_anonymous.py
@@ -0,0 +1,205 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_signup_anonymous_body import AuthSignupAnonymousBody
+from ...models.auth_token_response import AuthTokenResponse
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthSignupAnonymousBody | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/signup-anonymous",
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthTokenResponse | None:
+ if response.status_code == 201:
+ response_201 = AuthTokenResponse.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthTokenResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupAnonymousBody | Unset = UNSET,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ Create anonymous user
+
+ Create guest user without email/password.
+
+ User metadata (like display_name) can be included and will appear in realtime presence events.
+ Requires enable_anonymous_signins to be true.
+
+ Args:
+ body (AuthSignupAnonymousBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupAnonymousBody | Unset = UNSET,
+
+) -> Any | AuthTokenResponse | None:
+ """ Create anonymous user
+
+ Create guest user without email/password.
+
+ User metadata (like display_name) can be included and will appear in realtime presence events.
+ Requires enable_anonymous_signins to be true.
+
+ Args:
+ body (AuthSignupAnonymousBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupAnonymousBody | Unset = UNSET,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ Create anonymous user
+
+ Create guest user without email/password.
+
+ User metadata (like display_name) can be included and will appear in realtime presence events.
+ Requires enable_anonymous_signins to be true.
+
+ Args:
+ body (AuthSignupAnonymousBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthSignupAnonymousBody | Unset = UNSET,
+
+) -> Any | AuthTokenResponse | None:
+ """ Create anonymous user
+
+ Create guest user without email/password.
+
+ User metadata (like display_name) can be included and will appear in realtime presence events.
+ Requires enable_anonymous_signins to be true.
+
+ Args:
+ body (AuthSignupAnonymousBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_unlink_identity.py b/src/volcano_sdk/_generated/api/authentication/auth_unlink_identity.py
new file mode 100644
index 00000000..7bebe620
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_unlink_identity.py
@@ -0,0 +1,206 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ identity_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/auth/user/identities/{identity_id}".format(identity_id=quote(str(identity_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ identity_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Unlink an identity from the current user
+
+ Removes a non-primary identity and its attached sign-in methods. Refused
+ when the identity is the account's primary, its only identity, or when
+ removing it would leave the account with no way to sign in.
+
+ Args:
+ identity_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ identity_id=identity_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ identity_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Unlink an identity from the current user
+
+ Removes a non-primary identity and its attached sign-in methods. Refused
+ when the identity is the account's primary, its only identity, or when
+ removing it would leave the account with no way to sign in.
+
+ Args:
+ identity_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ identity_id=identity_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ identity_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Unlink an identity from the current user
+
+ Removes a non-primary identity and its attached sign-in methods. Refused
+ when the identity is the account's primary, its only identity, or when
+ removing it would leave the account with no way to sign in.
+
+ Args:
+ identity_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ identity_id=identity_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ identity_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Unlink an identity from the current user
+
+ Removes a non-primary identity and its attached sign-in methods. Refused
+ when the identity is the account's primary, its only identity, or when
+ removing it would leave the account with no way to sign in.
+
+ Args:
+ identity_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ identity_id=identity_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/authentication/auth_update_user.py b/src/volcano_sdk/_generated/api/authentication/auth_update_user.py
new file mode 100644
index 00000000..652e9755
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/authentication/auth_update_user.py
@@ -0,0 +1,211 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_update_user_body import AuthUpdateUserBody
+from ...models.auth_update_user_response_200 import AuthUpdateUserResponse200
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthUpdateUserBody | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/auth/user",
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthUpdateUserResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthUpdateUserResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthUpdateUserResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthUpdateUserBody | Unset = UNSET,
+
+) -> Response[AuthUpdateUserResponse200 | Error]:
+ """ Update user profile
+
+ Update password or metadata. Requires access token.
+
+ Args:
+ body (AuthUpdateUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthUpdateUserResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthUpdateUserBody | Unset = UNSET,
+
+) -> AuthUpdateUserResponse200 | Error | None:
+ """ Update user profile
+
+ Update password or metadata. Requires access token.
+
+ Args:
+ body (AuthUpdateUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthUpdateUserResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthUpdateUserBody | Unset = UNSET,
+
+) -> Response[AuthUpdateUserResponse200 | Error]:
+ """ Update user profile
+
+ Update password or metadata. Requires access token.
+
+ Args:
+ body (AuthUpdateUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthUpdateUserResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthUpdateUserBody | Unset = UNSET,
+
+) -> AuthUpdateUserResponse200 | Error | None:
+ """ Update user profile
+
+ Update password or metadata. Requires access token.
+
+ Args:
+ body (AuthUpdateUserBody | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthUpdateUserResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_branches/__init__.py b/src/volcano_sdk/_generated/api/database_branches/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/database_branches/create_database_branch.py b/src/volcano_sdk/_generated/api/database_branches/create_database_branch.py
new file mode 100644
index 00000000..b6e7fdca
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/create_database_branch.py
@@ -0,0 +1,285 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_database_branch_request import CreateDatabaseBranchRequest
+from ...models.database_branch import DatabaseBranch
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ *,
+ body: CreateDatabaseBranchRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/databases/{database_name}/branches".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseBranch | Error | None:
+ if response.status_code == 202:
+ response_202 = DatabaseBranch.from_dict(response.json())
+
+
+
+ return response_202
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseBranch | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseBranchRequest,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Create a branch of a database
+
+ Forks the database into a new branch. The branch starts as an exact copy
+ of the parent's data and diverges from there.
+
+ Provisioning is asynchronous: the response is `202` with the branch in
+ `provisioning` and no connection string. Poll the branch until it reports
+ `active`, at which point it carries its own connection string.
+
+ Retrying a create with a name that already exists returns `409` rather
+ than a second branch, so a retried request cannot silently consume two
+ slots of the branch allowance.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (CreateDatabaseBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseBranchRequest,
+
+) -> DatabaseBranch | Error | None:
+ """ Create a branch of a database
+
+ Forks the database into a new branch. The branch starts as an exact copy
+ of the parent's data and diverges from there.
+
+ Provisioning is asynchronous: the response is `202` with the branch in
+ `provisioning` and no connection string. Poll the branch until it reports
+ `active`, at which point it carries its own connection string.
+
+ Retrying a create with a name that already exists returns `409` rather
+ than a second branch, so a retried request cannot silently consume two
+ slots of the branch allowance.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (CreateDatabaseBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseBranchRequest,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Create a branch of a database
+
+ Forks the database into a new branch. The branch starts as an exact copy
+ of the parent's data and diverges from there.
+
+ Provisioning is asynchronous: the response is `202` with the branch in
+ `provisioning` and no connection string. Poll the branch until it reports
+ `active`, at which point it carries its own connection string.
+
+ Retrying a create with a name that already exists returns `409` rather
+ than a second branch, so a retried request cannot silently consume two
+ slots of the branch allowance.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (CreateDatabaseBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseBranchRequest,
+
+) -> DatabaseBranch | Error | None:
+ """ Create a branch of a database
+
+ Forks the database into a new branch. The branch starts as an exact copy
+ of the parent's data and diverges from there.
+
+ Provisioning is asynchronous: the response is `202` with the branch in
+ `provisioning` and no connection string. Poll the branch until it reports
+ `active`, at which point it carries its own connection string.
+
+ Retrying a create with a name that already exists returns `409` rather
+ than a second branch, so a retried request cannot silently consume two
+ slots of the branch allowance.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (CreateDatabaseBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_branches/delete_database_branch.py b/src/volcano_sdk/_generated/api/database_branches/delete_database_branch.py
new file mode 100644
index 00000000..dd1d857e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/delete_database_branch.py
@@ -0,0 +1,249 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.delete_database_branch_response_202 import DeleteDatabaseBranchResponse202
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/databases/{database_name}/branches/{branch_name}".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DeleteDatabaseBranchResponse202 | Error | None:
+ if response.status_code == 202:
+ response_202 = DeleteDatabaseBranchResponse202.from_dict(response.json())
+
+
+
+ return response_202
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DeleteDatabaseBranchResponse202 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DeleteDatabaseBranchResponse202 | Error]:
+ """ Delete a branch
+
+ Marks the branch for teardown and returns immediately. The branch stops
+ accepting connections at once; its fork and its row are removed by a
+ background job, so a provider outage cannot leave the call hanging or the
+ branch half-deleted.
+
+ Deleting a branch that is still provisioning is allowed and stops the
+ build, and repeating the call while teardown is in progress is accepted
+ again. Once the branch is gone the call returns `404`.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DeleteDatabaseBranchResponse202 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DeleteDatabaseBranchResponse202 | Error | None:
+ """ Delete a branch
+
+ Marks the branch for teardown and returns immediately. The branch stops
+ accepting connections at once; its fork and its row are removed by a
+ background job, so a provider outage cannot leave the call hanging or the
+ branch half-deleted.
+
+ Deleting a branch that is still provisioning is allowed and stops the
+ build, and repeating the call while teardown is in progress is accepted
+ again. Once the branch is gone the call returns `404`.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DeleteDatabaseBranchResponse202 | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DeleteDatabaseBranchResponse202 | Error]:
+ """ Delete a branch
+
+ Marks the branch for teardown and returns immediately. The branch stops
+ accepting connections at once; its fork and its row are removed by a
+ background job, so a provider outage cannot leave the call hanging or the
+ branch half-deleted.
+
+ Deleting a branch that is still provisioning is allowed and stops the
+ build, and repeating the call while teardown is in progress is accepted
+ again. Once the branch is gone the call returns `404`.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DeleteDatabaseBranchResponse202 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DeleteDatabaseBranchResponse202 | Error | None:
+ """ Delete a branch
+
+ Marks the branch for teardown and returns immediately. The branch stops
+ accepting connections at once; its fork and its row are removed by a
+ background job, so a provider outage cannot leave the call hanging or the
+ branch half-deleted.
+
+ Deleting a branch that is still provisioning is allowed and stops the
+ build, and repeating the call while teardown is in progress is accepted
+ again. Once the branch is gone the call returns `404`.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DeleteDatabaseBranchResponse202 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_branches/get_database_branch.py b/src/volcano_sdk/_generated/api/database_branches/get_database_branch.py
new file mode 100644
index 00000000..d6c403b3
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/get_database_branch.py
@@ -0,0 +1,225 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_branch import DatabaseBranch
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/databases/{database_name}/branches/{branch_name}".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseBranch | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseBranch.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseBranch | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Get a branch
+
+ Returns the branch, including its connection string once it is `active`.
+ Poll this after creating a branch to learn when it is connectable.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranch | Error | None:
+ """ Get a branch
+
+ Returns the branch, including its connection string once it is `active`.
+ Poll this after creating a branch to learn when it is connectable.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Get a branch
+
+ Returns the branch, including its connection string once it is `active`.
+ Poll this after creating a branch to learn when it is connectable.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranch | Error | None:
+ """ Get a branch
+
+ Returns the branch, including its connection string once it is `active`.
+ Poll this after creating a branch to learn when it is connectable.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_branches/list_database_branches.py b/src/volcano_sdk/_generated/api/database_branches/list_database_branches.py
new file mode 100644
index 00000000..09616c3d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/list_database_branches.py
@@ -0,0 +1,224 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_branch_list import DatabaseBranchList
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/databases/{database_name}/branches".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseBranchList | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseBranchList.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseBranchList | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranchList | Error]:
+ """ List a database's branches
+
+ Returns every branch of the database, including those still provisioning
+ and those that failed, since each still holds a name.
+
+ Connection strings are omitted. Fetch a single branch to get its
+ connection string.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranchList | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranchList | Error | None:
+ """ List a database's branches
+
+ Returns every branch of the database, including those still provisioning
+ and those that failed, since each still holds a name.
+
+ Connection strings are omitted. Fetch a single branch to get its
+ connection string.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranchList | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranchList | Error]:
+ """ List a database's branches
+
+ Returns every branch of the database, including those still provisioning
+ and those that failed, since each still holds a name.
+
+ Connection strings are omitted. Fetch a single branch to get its
+ connection string.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranchList | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranchList | Error | None:
+ """ List a database's branches
+
+ Returns every branch of the database, including those still provisioning
+ and those that failed, since each still holds a name.
+
+ Connection strings are omitted. Fetch a single branch to get its
+ connection string.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranchList | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_branches/reset_database_branch.py b/src/volcano_sdk/_generated/api/database_branches/reset_database_branch.py
new file mode 100644
index 00000000..9c73a9f3
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/reset_database_branch.py
@@ -0,0 +1,268 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_branch import DatabaseBranch
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/databases/{database_name}/branches/{branch_name}/reset".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseBranch | Error | None:
+ if response.status_code == 202:
+ response_202 = DatabaseBranch.from_dict(response.json())
+
+
+
+ return response_202
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseBranch | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Reset a branch to its parent's current state
+
+ Discards everything written on the branch and re-forks it from the
+ parent as it is now.
+
+ Returns immediately with the branch in `provisioning`. The rewind runs in
+ the background; poll the branch until it reports `active` before
+ connecting again.
+
+ The branch keeps its name and its connection string, so anything holding
+ that string keeps working once it is active again, and its lifetime is
+ re-armed to the duration it was created with. The branch does not serve
+ connections for the duration of the reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranch | Error | None:
+ """ Reset a branch to its parent's current state
+
+ Discards everything written on the branch and re-forks it from the
+ parent as it is now.
+
+ Returns immediately with the branch in `provisioning`. The rewind runs in
+ the background; poll the branch until it reports `active` before
+ connecting again.
+
+ The branch keeps its name and its connection string, so anything holding
+ that string keeps working once it is active again, and its lifetime is
+ re-armed to the duration it was created with. The branch does not serve
+ connections for the duration of the reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Reset a branch to its parent's current state
+
+ Discards everything written on the branch and re-forks it from the
+ parent as it is now.
+
+ Returns immediately with the branch in `provisioning`. The rewind runs in
+ the background; poll the branch until it reports `active` before
+ connecting again.
+
+ The branch keeps its name and its connection string, so anything holding
+ that string keeps working once it is active again, and its lifetime is
+ re-armed to the duration it was created with. The branch does not serve
+ connections for the duration of the reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranch | Error | None:
+ """ Reset a branch to its parent's current state
+
+ Discards everything written on the branch and re-forks it from the
+ parent as it is now.
+
+ Returns immediately with the branch in `provisioning`. The rewind runs in
+ the background; poll the branch until it reports `active` before
+ connecting again.
+
+ The branch keeps its name and its connection string, so anything holding
+ that string keeps working once it is active again, and its lifetime is
+ re-armed to the duration it was created with. The branch does not serve
+ connections for the duration of the reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_branches/reset_database_branch_password.py b/src/volcano_sdk/_generated/api/database_branches/reset_database_branch_password.py
new file mode 100644
index 00000000..e7d7a20b
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/reset_database_branch_password.py
@@ -0,0 +1,244 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_branch import DatabaseBranch
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/databases/{database_name}/branches/{branch_name}/reset-password".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseBranch | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseBranch.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseBranch | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Rotate a branch's password
+
+ Issues a new password for the branch and invalidates the previous
+ connection string. Existing connections are not interrupted; new ones
+ must use the returned string.
+
+ The parent database's credentials are untouched.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranch | Error | None:
+ """ Rotate a branch's password
+
+ Issues a new password for the branch and invalidates the previous
+ connection string. Existing connections are not interrupted; new ones
+ must use the returned string.
+
+ The parent database's credentials are untouched.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Rotate a branch's password
+
+ Issues a new password for the branch and invalidates the previous
+ connection string. Existing connections are not interrupted; new ones
+ must use the returned string.
+
+ The parent database's credentials are untouched.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseBranch | Error | None:
+ """ Rotate a branch's password
+
+ Issues a new password for the branch and invalidates the previous
+ connection string. Existing connections are not interrupted; new ones
+ must use the returned string.
+
+ The parent database's credentials are untouched.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_branches/update_database_branch.py b/src/volcano_sdk/_generated/api/database_branches/update_database_branch.py
new file mode 100644
index 00000000..87e5c3be
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_branches/update_database_branch.py
@@ -0,0 +1,267 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_branch import DatabaseBranch
+from ...models.error import Error
+from ...models.update_database_branch_request import UpdateDatabaseBranchRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ body: UpdateDatabaseBranchRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/projects/{id}/databases/{database_name}/branches/{branch_name}".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseBranch | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseBranch.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseBranch | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseBranchRequest,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Extend a branch's lifetime
+
+ Replaces the branch's lifetime and restarts the countdown from now, so a
+ branch you are still working on is not swept mid-session. The new
+ duration is remembered, so a later reset re-arms the same lifetime.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+ body (UpdateDatabaseBranchRequest): Replace the branch's lifetime and restart its
+ countdown from now.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseBranchRequest,
+
+) -> DatabaseBranch | Error | None:
+ """ Extend a branch's lifetime
+
+ Replaces the branch's lifetime and restarts the countdown from now, so a
+ branch you are still working on is not swept mid-session. The new
+ duration is remembered, so a later reset re-arms the same lifetime.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+ body (UpdateDatabaseBranchRequest): Replace the branch's lifetime and restart its
+ countdown from now.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseBranchRequest,
+
+) -> Response[DatabaseBranch | Error]:
+ """ Extend a branch's lifetime
+
+ Replaces the branch's lifetime and restarts the countdown from now, so a
+ branch you are still working on is not swept mid-session. The new
+ duration is remembered, so a later reset re-arms the same lifetime.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+ body (UpdateDatabaseBranchRequest): Replace the branch's lifetime and restart its
+ countdown from now.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseBranch | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseBranchRequest,
+
+) -> DatabaseBranch | Error | None:
+ """ Extend a branch's lifetime
+
+ Replaces the branch's lifetime and restarts the countdown from now, so a
+ branch you are still working on is not swept mid-session. The new
+ duration is remembered, so a later reset re-arms the same lifetime.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ branch_name (str):
+ body (UpdateDatabaseBranchRequest): Replace the branch's lifetime and restart its
+ countdown from now.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseBranch | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/__init__.py b/src/volcano_sdk/_generated/api/database_queries/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_branch_delete.py b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_delete.py
new file mode 100644
index 00000000..612aff17
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_delete.py
@@ -0,0 +1,288 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_delete_request import DatabaseDeleteRequest
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ branch_name: str,
+ *,
+ body: DatabaseDeleteRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/branches/{branch_name}/query/delete".format(database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_branch_insert.py b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_insert.py
new file mode 100644
index 00000000..f9634b30
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_insert.py
@@ -0,0 +1,292 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_insert_request import DatabaseInsertRequest
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ branch_name: str,
+ *,
+ body: DatabaseInsertRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/branches/{branch_name}/query/insert".format(database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_branch_ping.py b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_ping.py
new file mode 100644
index 00000000..9812eff7
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_ping.py
@@ -0,0 +1,269 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ branch_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/branches/{branch_name}/query/ping".format(database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_branch_select.py b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_select.py
new file mode 100644
index 00000000..59a6df4e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_select.py
@@ -0,0 +1,308 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.database_select_request import DatabaseSelectRequest
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ branch_name: str,
+ *,
+ body: DatabaseSelectRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/branches/{branch_name}/query/select".format(database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_branch_update.py b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_update.py
new file mode 100644
index 00000000..d33ef1cc
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_branch_update.py
@@ -0,0 +1,296 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.database_update_request import DatabaseUpdateRequest
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ branch_name: str,
+ *,
+ body: DatabaseUpdateRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/branches/{branch_name}/query/update".format(database_name=quote(str(database_name), safe=""),branch_name=quote(str(branch_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+branch_name=branch_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ branch_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ **Branch-targeted.** Runs against the named branch instead of the parent
+ database, using the branch's own credentials. The branch must be `active`
+ and unexpired. Nothing about this request can reach the parent's data.
+
+ Args:
+ database_name (str):
+ branch_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+branch_name=branch_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_delete.py b/src/volcano_sdk/_generated/api/database_queries/query_database_delete.py
new file mode 100644
index 00000000..f0c99d98
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_delete.py
@@ -0,0 +1,259 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_delete_request import DatabaseDeleteRequest
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ *,
+ body: DatabaseDeleteRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/query/delete".format(database_name=quote(str(database_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseDeleteRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Delete data from database (REST API)
+
+ Delete rows from your database using REST API.
+
+ **Safety:** Requires at least one filter to prevent accidental mass deletions
+
+ **Security:** Row-Level Security ensures you can only delete data you have access to
+
+ **Note:** If RLS blocks the delete, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseDeleteRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_insert.py b/src/volcano_sdk/_generated/api/database_queries/query_database_insert.py
new file mode 100644
index 00000000..ec0e756b
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_insert.py
@@ -0,0 +1,263 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_insert_request import DatabaseInsertRequest
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ *,
+ body: DatabaseInsertRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/query/insert".format(database_name=quote(str(database_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ Args:
+ database_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ Args:
+ database_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ Args:
+ database_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseInsertRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Insert data into database (REST API)
+
+ Insert new rows into your database using REST API.
+
+ **Authentication:** Requires auth user access token
+
+ **Auto-set user_id:** If your table has a trigger using `auth.uid()`,
+ user_id will be automatically set to the authenticated user
+
+ **Security:** Row-Level Security policies are enforced
+
+ Args:
+ database_name (str):
+ body (DatabaseInsertRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_ping.py b/src/volcano_sdk/_generated/api/database_queries/query_database_ping.py
new file mode 100644
index 00000000..79ea7174
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_ping.py
@@ -0,0 +1,240 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/query/ping".format(database_name=quote(str(database_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ Args:
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ Args:
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ Args:
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Database connectivity probe (REST API)
+
+ Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
+ same authentication, status/bandwidth gating, and metering as the other
+ `/query/*` endpoints.
+
+ Unlike those endpoints, ping takes **no request body** and performs **no
+ table-name validation**, so it works on any database — including a freshly
+ provisioned, empty one. It is a real committed round-trip through pgproxy,
+ so a `200` means the database is reachable and queryable. Used by the
+ dashboard's database connection test.
+
+ Args:
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_select.py b/src/volcano_sdk/_generated/api/database_queries/query_database_select.py
new file mode 100644
index 00000000..8149710e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_select.py
@@ -0,0 +1,279 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.database_select_request import DatabaseSelectRequest
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ *,
+ body: DatabaseSelectRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/query/select".format(database_name=quote(str(database_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use functions with direct SQL
+
+ Args:
+ database_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use functions with direct SQL
+
+ Args:
+ database_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use functions with direct SQL
+
+ Args:
+ database_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseSelectRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Query database with SELECT (REST API)
+
+ Query your database using a simple REST API - no SQL required!
+
+ **Authentication:** Requires auth user access token (from signup/signin)
+
+ **Row-Level Security:** Automatically enforced - you see only data you have access to
+
+ **Use Cases:**
+ - Query from browser/mobile apps
+ - Simple data retrieval
+ - Filtered searches with sorting and pagination
+
+ **Note:** For complex queries (JOINs, CTEs), use functions with direct SQL
+
+ Args:
+ database_name (str):
+ body (DatabaseSelectRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/database_queries/query_database_update.py b/src/volcano_sdk/_generated/api/database_queries/query_database_update.py
new file mode 100644
index 00000000..a27b100d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/database_queries/query_database_update.py
@@ -0,0 +1,267 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_query_result import DatabaseQueryResult
+from ...models.database_update_request import DatabaseUpdateRequest
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ database_name: str,
+ *,
+ body: DatabaseUpdateRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/databases/{database_name}/query/update".format(database_name=quote(str(database_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryResult | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryResult | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return sync_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> Response[DatabaseQueryResult | Error]:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryResult | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ database_name=database_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: DatabaseUpdateRequest,
+
+) -> DatabaseQueryResult | Error | None:
+ """ Update data in database (REST API)
+
+ Update existing rows in your database using REST API.
+
+ **Security:** Row-Level Security ensures you can only update data you have access to
+
+ **Safety:** Requires at least one filter to prevent accidental mass updates. A
+ request with no `filters` is rejected with `400` (mirrors delete). This matters
+ for service-key queries, which run with full access and bypass RLS.
+
+ **Note:** If RLS blocks the update, an empty result is returned (not an error)
+
+ Args:
+ database_name (str):
+ body (DatabaseUpdateRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryResult | Error
+ """
+
+
+ return (await asyncio_detailed(
+ database_name=database_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/__init__.py b/src/volcano_sdk/_generated/api/databases/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/databases/create_database.py b/src/volcano_sdk/_generated/api/databases/create_database.py
new file mode 100644
index 00000000..cf916500
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/create_database.py
@@ -0,0 +1,232 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_database_request import CreateDatabaseRequest
+from ...models.database import Database
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateDatabaseRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/databases".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Database | Error | None:
+ if response.status_code == 201:
+ response_201 = Database.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Database | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseRequest,
+
+) -> Response[Database | Error]:
+ """ Create a new serverless PostgreSQL database
+
+ Creates a serverless PostgreSQL database in the project.
+ Each project can contain up to 100 databases. Requests over this cap return 403.
+
+ Args:
+ id (UUID):
+ body (CreateDatabaseRequest): Create a new PostgreSQL database. Volcano automatically sets
+ up:
+ - Auth helpers (auth.uid(), auth.email(), auth.role())
+ - Database roles (anon for unauthenticated, authenticated for signed-in users)
+ - Secure multi-tenant isolation
+ - Ready for Row-Level Security
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Database | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseRequest,
+
+) -> Database | Error | None:
+ """ Create a new serverless PostgreSQL database
+
+ Creates a serverless PostgreSQL database in the project.
+ Each project can contain up to 100 databases. Requests over this cap return 403.
+
+ Args:
+ id (UUID):
+ body (CreateDatabaseRequest): Create a new PostgreSQL database. Volcano automatically sets
+ up:
+ - Auth helpers (auth.uid(), auth.email(), auth.role())
+ - Database roles (anon for unauthenticated, authenticated for signed-in users)
+ - Secure multi-tenant isolation
+ - Ready for Row-Level Security
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Database | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseRequest,
+
+) -> Response[Database | Error]:
+ """ Create a new serverless PostgreSQL database
+
+ Creates a serverless PostgreSQL database in the project.
+ Each project can contain up to 100 databases. Requests over this cap return 403.
+
+ Args:
+ id (UUID):
+ body (CreateDatabaseRequest): Create a new PostgreSQL database. Volcano automatically sets
+ up:
+ - Auth helpers (auth.uid(), auth.email(), auth.role())
+ - Database roles (anon for unauthenticated, authenticated for signed-in users)
+ - Secure multi-tenant isolation
+ - Ready for Row-Level Security
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Database | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateDatabaseRequest,
+
+) -> Database | Error | None:
+ """ Create a new serverless PostgreSQL database
+
+ Creates a serverless PostgreSQL database in the project.
+ Each project can contain up to 100 databases. Requests over this cap return 403.
+
+ Args:
+ id (UUID):
+ body (CreateDatabaseRequest): Create a new PostgreSQL database. Volcano automatically sets
+ up:
+ - Auth helpers (auth.uid(), auth.email(), auth.role())
+ - Database roles (anon for unauthenticated, authenticated for signed-in users)
+ - Secure multi-tenant isolation
+ - Ready for Row-Level Security
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Database | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/delete_database.py b/src/volcano_sdk/_generated/api/databases/delete_database.py
new file mode 100644
index 00000000..61b65365
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/delete_database.py
@@ -0,0 +1,225 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.delete_database_response_202 import DeleteDatabaseResponse202
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/databases/{database_name}".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | DeleteDatabaseResponse202 | None:
+ if response.status_code == 202:
+ response_202 = DeleteDatabaseResponse202.from_dict(response.json())
+
+
+
+ return response_202
+
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | DeleteDatabaseResponse202]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | DeleteDatabaseResponse202]:
+ """ Delete a database
+
+ Deletes a database and the instance backing it. When the instance is
+ removed synchronously the database row is deleted and the response is
+ `204`. If the instance cannot be deleted right away, the database row
+ is retained (status `deleting`) and its teardown is handed to the
+ background reconciler, which retries the deletion and removes the row
+ once the instance is gone; in that case the response is `202`. The database row is
+ never dropped while its instance still exists, so an instance is
+ never orphaned without a record to retry from.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | DeleteDatabaseResponse202]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | DeleteDatabaseResponse202 | None:
+ """ Delete a database
+
+ Deletes a database and the instance backing it. When the instance is
+ removed synchronously the database row is deleted and the response is
+ `204`. If the instance cannot be deleted right away, the database row
+ is retained (status `deleting`) and its teardown is handed to the
+ background reconciler, which retries the deletion and removes the row
+ once the instance is gone; in that case the response is `202`. The database row is
+ never dropped while its instance still exists, so an instance is
+ never orphaned without a record to retry from.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | DeleteDatabaseResponse202
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | DeleteDatabaseResponse202]:
+ """ Delete a database
+
+ Deletes a database and the instance backing it. When the instance is
+ removed synchronously the database row is deleted and the response is
+ `204`. If the instance cannot be deleted right away, the database row
+ is retained (status `deleting`) and its teardown is handed to the
+ background reconciler, which retries the deletion and removes the row
+ once the instance is gone; in that case the response is `202`. The database row is
+ never dropped while its instance still exists, so an instance is
+ never orphaned without a record to retry from.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | DeleteDatabaseResponse202]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | DeleteDatabaseResponse202 | None:
+ """ Delete a database
+
+ Deletes a database and the instance backing it. When the instance is
+ removed synchronously the database row is deleted and the response is
+ `204`. If the instance cannot be deleted right away, the database row
+ is retained (status `deleting`) and its teardown is handed to the
+ background reconciler, which retries the deletion and removes the row
+ once the instance is gone; in that case the response is `202`. The database row is
+ never dropped while its instance still exists, so an instance is
+ never orphaned without a record to retry from.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | DeleteDatabaseResponse202
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/get_database.py b/src/volcano_sdk/_generated/api/databases/get_database.py
new file mode 100644
index 00000000..85ea1254
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/get_database.py
@@ -0,0 +1,185 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database import Database
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/databases/{database_name}".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Database | None:
+ if response.status_code == 200:
+ response_200 = Database.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Database]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Database]:
+ """ Get database details
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Database]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Database | None:
+ """ Get database details
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Database
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Database]:
+ """ Get database details
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Database]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Database | None:
+ """ Get database details
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Database
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/get_database_stats.py b/src/volcano_sdk/_generated/api/databases/get_database_stats.py
new file mode 100644
index 00000000..880da6ef
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/get_database_stats.py
@@ -0,0 +1,292 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_stats import DatabaseStats
+from ...models.error import Error
+from ...models.get_database_stats_granularity import check_get_database_stats_granularity
+from ...models.get_database_stats_granularity import GetDatabaseStatsGranularity
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ *,
+ from_: datetime.datetime | Unset = UNSET,
+ to: datetime.datetime | Unset = UNSET,
+ granularity: GetDatabaseStatsGranularity | Unset = 'hourly',
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_from_: str | Unset = UNSET
+ if not isinstance(from_, Unset):
+ json_from_ = from_.isoformat()
+ params["from"] = json_from_
+
+ json_to: str | Unset = UNSET
+ if not isinstance(to, Unset):
+ json_to = to.isoformat()
+ params["to"] = json_to
+
+ json_granularity: str | Unset = UNSET
+ if not isinstance(granularity, Unset):
+ json_granularity = granularity
+
+ params["granularity"] = json_granularity
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/databases/{database_name}/stats".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseStats | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseStats.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseStats | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.datetime | Unset = UNSET,
+ to: datetime.datetime | Unset = UNSET,
+ granularity: GetDatabaseStatsGranularity | Unset = 'hourly',
+
+) -> Response[DatabaseStats | Error]:
+ """ Get database consumption metrics
+
+ Retrieve consumption metrics including storage, compute time, and data transfer.
+ Metrics are aggregated at the project level. Defaults to last 24 hours.
+
+ **Note:** Advanced metrics require an upgraded plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ from_ (datetime.datetime | Unset):
+ to (datetime.datetime | Unset):
+ granularity (GetDatabaseStatsGranularity | Unset): Default: 'hourly'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseStats | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+from_=from_,
+to=to,
+granularity=granularity,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.datetime | Unset = UNSET,
+ to: datetime.datetime | Unset = UNSET,
+ granularity: GetDatabaseStatsGranularity | Unset = 'hourly',
+
+) -> DatabaseStats | Error | None:
+ """ Get database consumption metrics
+
+ Retrieve consumption metrics including storage, compute time, and data transfer.
+ Metrics are aggregated at the project level. Defaults to last 24 hours.
+
+ **Note:** Advanced metrics require an upgraded plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ from_ (datetime.datetime | Unset):
+ to (datetime.datetime | Unset):
+ granularity (GetDatabaseStatsGranularity | Unset): Default: 'hourly'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseStats | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+from_=from_,
+to=to,
+granularity=granularity,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.datetime | Unset = UNSET,
+ to: datetime.datetime | Unset = UNSET,
+ granularity: GetDatabaseStatsGranularity | Unset = 'hourly',
+
+) -> Response[DatabaseStats | Error]:
+ """ Get database consumption metrics
+
+ Retrieve consumption metrics including storage, compute time, and data transfer.
+ Metrics are aggregated at the project level. Defaults to last 24 hours.
+
+ **Note:** Advanced metrics require an upgraded plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ from_ (datetime.datetime | Unset):
+ to (datetime.datetime | Unset):
+ granularity (GetDatabaseStatsGranularity | Unset): Default: 'hourly'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseStats | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+from_=from_,
+to=to,
+granularity=granularity,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ from_: datetime.datetime | Unset = UNSET,
+ to: datetime.datetime | Unset = UNSET,
+ granularity: GetDatabaseStatsGranularity | Unset = 'hourly',
+
+) -> DatabaseStats | Error | None:
+ """ Get database consumption metrics
+
+ Retrieve consumption metrics including storage, compute time, and data transfer.
+ Metrics are aggregated at the project level. Defaults to last 24 hours.
+
+ **Note:** Advanced metrics require an upgraded plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ from_ (datetime.datetime | Unset):
+ to (datetime.datetime | Unset):
+ granularity (GetDatabaseStatsGranularity | Unset): Default: 'hourly'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseStats | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+from_=from_,
+to=to,
+granularity=granularity,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/get_project_database_queries.py b/src/volcano_sdk/_generated/api/databases/get_project_database_queries.py
new file mode 100644
index 00000000..646bb34e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/get_project_database_queries.py
@@ -0,0 +1,267 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database_query_performance_response import DatabaseQueryPerformanceResponse
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ *,
+ limit: int | Unset = 10,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["limit"] = limit
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/databases/{database_name}/queries".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DatabaseQueryPerformanceResponse | Error | None:
+ if response.status_code == 200:
+ response_200 = DatabaseQueryPerformanceResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DatabaseQueryPerformanceResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+
+) -> Response[DatabaseQueryPerformanceResponse | Error]:
+ """ Get database queries
+
+ Returns the database's current top queries from pg_stat_statements
+ ranked by total execution time.
+
+ **PRO plan required.** This endpoint is only available to projects owned
+ by users on the PRO billing plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryPerformanceResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+limit=limit,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+
+) -> DatabaseQueryPerformanceResponse | Error | None:
+ """ Get database queries
+
+ Returns the database's current top queries from pg_stat_statements
+ ranked by total execution time.
+
+ **PRO plan required.** This endpoint is only available to projects owned
+ by users on the PRO billing plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryPerformanceResponse | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+limit=limit,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+
+) -> Response[DatabaseQueryPerformanceResponse | Error]:
+ """ Get database queries
+
+ Returns the database's current top queries from pg_stat_statements
+ ranked by total execution time.
+
+ **PRO plan required.** This endpoint is only available to projects owned
+ by users on the PRO billing plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DatabaseQueryPerformanceResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+limit=limit,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+
+) -> DatabaseQueryPerformanceResponse | Error | None:
+ """ Get database queries
+
+ Returns the database's current top queries from pg_stat_statements
+ ranked by total execution time.
+
+ **PRO plan required.** This endpoint is only available to projects owned
+ by users on the PRO billing plan.
+
+ Args:
+ id (UUID):
+ database_name (str):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DatabaseQueryPerformanceResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+limit=limit,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/list_database_regions.py b/src/volcano_sdk/_generated/api/databases/list_database_regions.py
new file mode 100644
index 00000000..52e8af11
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/list_database_regions.py
@@ -0,0 +1,167 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.list_database_regions_response_200_item import ListDatabaseRegionsResponse200Item
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/databases/regions",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> list[ListDatabaseRegionsResponse200Item] | None:
+ if response.status_code == 200:
+ response_200 = []
+ _response_200 = response.json()
+ for response_200_item_data in (_response_200):
+ response_200_item = ListDatabaseRegionsResponse200Item.from_dict(response_200_item_data)
+
+
+
+ response_200.append(response_200_item)
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[list[ListDatabaseRegionsResponse200Item]]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[list[ListDatabaseRegionsResponse200Item]]:
+ """ List platform-supported regions for database provisioning
+
+ Returns the regions enabled for database provisioning in this platform environment.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[ListDatabaseRegionsResponse200Item]]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> list[ListDatabaseRegionsResponse200Item] | None:
+ """ List platform-supported regions for database provisioning
+
+ Returns the regions enabled for database provisioning in this platform environment.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[ListDatabaseRegionsResponse200Item]
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[list[ListDatabaseRegionsResponse200Item]]:
+ """ List platform-supported regions for database provisioning
+
+ Returns the regions enabled for database provisioning in this platform environment.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[ListDatabaseRegionsResponse200Item]]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> list[ListDatabaseRegionsResponse200Item] | None:
+ """ List platform-supported regions for database provisioning
+
+ Returns the regions enabled for database provisioning in this platform environment.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[ListDatabaseRegionsResponse200Item]
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/list_databases.py b/src/volcano_sdk/_generated/api/databases/list_databases.py
new file mode 100644
index 00000000..1385eca2
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/list_databases.py
@@ -0,0 +1,293 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.paginated_databases import PaginatedDatabases
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/databases".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> PaginatedDatabases | None:
+ if response.status_code == 200:
+ response_200 = PaginatedDatabases.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[PaginatedDatabases]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[PaginatedDatabases]:
+ """ List all databases for a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit`. Cursor mode uses `cursor` and `limit`, supports `search`
+ (case-insensitive name match), and returns `next_cursor`/`prev_cursor`.
+ The optional `status` filter applies in both modes and is bound to the
+ cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[PaginatedDatabases]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> PaginatedDatabases | None:
+ """ List all databases for a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit`. Cursor mode uses `cursor` and `limit`, supports `search`
+ (case-insensitive name match), and returns `next_cursor`/`prev_cursor`.
+ The optional `status` filter applies in both modes and is bound to the
+ cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ PaginatedDatabases
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[PaginatedDatabases]:
+ """ List all databases for a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit`. Cursor mode uses `cursor` and `limit`, supports `search`
+ (case-insensitive name match), and returns `next_cursor`/`prev_cursor`.
+ The optional `status` filter applies in both modes and is bound to the
+ cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[PaginatedDatabases]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> PaginatedDatabases | None:
+ """ List all databases for a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit`. Cursor mode uses `cursor` and `limit`, supports `search`
+ (case-insensitive name match), and returns `next_cursor`/`prev_cursor`.
+ The optional `status` filter applies in both modes and is bound to the
+ cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ PaginatedDatabases
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/list_postgres_versions.py b/src/volcano_sdk/_generated/api/databases/list_postgres_versions.py
new file mode 100644
index 00000000..19122aab
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/list_postgres_versions.py
@@ -0,0 +1,167 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.list_postgres_versions_response_200_item import ListPostgresVersionsResponse200Item
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/databases/postgres-versions",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> list[ListPostgresVersionsResponse200Item] | None:
+ if response.status_code == 200:
+ response_200 = []
+ _response_200 = response.json()
+ for response_200_item_data in (_response_200):
+ response_200_item = ListPostgresVersionsResponse200Item.from_dict(response_200_item_data)
+
+
+
+ response_200.append(response_200_item)
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[list[ListPostgresVersionsResponse200Item]]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[list[ListPostgresVersionsResponse200Item]]:
+ """ List available PostgreSQL versions
+
+ Returns a list of supported PostgreSQL major versions for database provisioning.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[ListPostgresVersionsResponse200Item]]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> list[ListPostgresVersionsResponse200Item] | None:
+ """ List available PostgreSQL versions
+
+ Returns a list of supported PostgreSQL major versions for database provisioning.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[ListPostgresVersionsResponse200Item]
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[list[ListPostgresVersionsResponse200Item]]:
+ """ List available PostgreSQL versions
+
+ Returns a list of supported PostgreSQL major versions for database provisioning.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[ListPostgresVersionsResponse200Item]]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> list[ListPostgresVersionsResponse200Item] | None:
+ """ List available PostgreSQL versions
+
+ Returns a list of supported PostgreSQL major versions for database provisioning.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[ListPostgresVersionsResponse200Item]
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/reset_database_password.py b/src/volcano_sdk/_generated/api/databases/reset_database_password.py
new file mode 100644
index 00000000..2921fa63
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/reset_database_password.py
@@ -0,0 +1,205 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.reset_database_password_response_200 import ResetDatabasePasswordResponse200
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/databases/{database_name}/reset-password".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ResetDatabasePasswordResponse200 | None:
+ if response.status_code == 200:
+ response_200 = ResetDatabasePasswordResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ResetDatabasePasswordResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ResetDatabasePasswordResponse200]:
+ """ Reset database password
+
+ Rotates the Volcano-managed PostgreSQL password used by clients when connecting
+ through pgproxy. This does not rotate or expose the internal owner password.
+ The returned password and connection string are the only client credentials that
+ will authenticate through pgproxy after reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ResetDatabasePasswordResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> ResetDatabasePasswordResponse200 | None:
+ """ Reset database password
+
+ Rotates the Volcano-managed PostgreSQL password used by clients when connecting
+ through pgproxy. This does not rotate or expose the internal owner password.
+ The returned password and connection string are the only client credentials that
+ will authenticate through pgproxy after reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ResetDatabasePasswordResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ResetDatabasePasswordResponse200]:
+ """ Reset database password
+
+ Rotates the Volcano-managed PostgreSQL password used by clients when connecting
+ through pgproxy. This does not rotate or expose the internal owner password.
+ The returned password and connection string are the only client credentials that
+ will authenticate through pgproxy after reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ResetDatabasePasswordResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> ResetDatabasePasswordResponse200 | None:
+ """ Reset database password
+
+ Rotates the Volcano-managed PostgreSQL password used by clients when connecting
+ through pgproxy. This does not rotate or expose the internal owner password.
+ The returned password and connection string are the only client credentials that
+ will authenticate through pgproxy after reset.
+
+ Args:
+ id (UUID):
+ database_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ResetDatabasePasswordResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/databases/update_database_type.py b/src/volcano_sdk/_generated/api/databases/update_database_type.py
new file mode 100644
index 00000000..df6daba3
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/databases/update_database_type.py
@@ -0,0 +1,253 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.database import Database
+from ...models.update_database_type_request import UpdateDatabaseTypeRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ database_name: str,
+ *,
+ body: UpdateDatabaseTypeRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/projects/{id}/databases/{database_name}/type".format(id=quote(str(id), safe=""),database_name=quote(str(database_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Database | None:
+ if response.status_code == 200:
+ response_200 = Database.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Database]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseTypeRequest,
+
+) -> Response[Any | Database]:
+ """ Update database size
+
+ Change the size tier of a database. This may briefly interrupt active connections.
+
+ **Available sizes:**
+ - `volcano-db-xs`: Up to ~1GB RAM - Development, small apps
+ - `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic
+ - `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications
+ - `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets
+ - `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads
+ - `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (UpdateDatabaseTypeRequest): Update database compute size tier
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Database]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseTypeRequest,
+
+) -> Any | Database | None:
+ """ Update database size
+
+ Change the size tier of a database. This may briefly interrupt active connections.
+
+ **Available sizes:**
+ - `volcano-db-xs`: Up to ~1GB RAM - Development, small apps
+ - `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic
+ - `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications
+ - `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets
+ - `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads
+ - `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (UpdateDatabaseTypeRequest): Update database compute size tier
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Database
+ """
+
+
+ return sync_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseTypeRequest,
+
+) -> Response[Any | Database]:
+ """ Update database size
+
+ Change the size tier of a database. This may briefly interrupt active connections.
+
+ **Available sizes:**
+ - `volcano-db-xs`: Up to ~1GB RAM - Development, small apps
+ - `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic
+ - `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications
+ - `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets
+ - `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads
+ - `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (UpdateDatabaseTypeRequest): Update database compute size tier
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Database]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+database_name=database_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ database_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateDatabaseTypeRequest,
+
+) -> Any | Database | None:
+ """ Update database size
+
+ Change the size tier of a database. This may briefly interrupt active connections.
+
+ **Available sizes:**
+ - `volcano-db-xs`: Up to ~1GB RAM - Development, small apps
+ - `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic
+ - `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications
+ - `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets
+ - `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads
+ - `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale
+
+ Args:
+ id (UUID):
+ database_name (str):
+ body (UpdateDatabaseTypeRequest): Update database compute size tier
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Database
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+database_name=database_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/__init__.py b/src/volcano_sdk/_generated/api/frontends/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/frontends/create_frontend.py b/src/volcano_sdk/_generated/api/frontends/create_frontend.py
new file mode 100644
index 00000000..e89f2827
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/create_frontend.py
@@ -0,0 +1,369 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_frontend_body import CreateFrontendBody
+from ...models.error import Error
+from ...models.frontend import Frontend
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateFrontendBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/frontends".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["files"] = body.to_multipart()
+
+ headers["Content-Type"] = "multipart/form-data; boundary=+++"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Frontend | None:
+ if response.status_code == 200:
+ response_200 = Frontend.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 201:
+ response_201 = Frontend.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Frontend]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendBody,
+
+) -> Response[Error | Frontend]:
+ """ Create a new frontend deployment
+
+ Creates and deploys a frontend for the project.
+ If a frontend with the same name already exists in the project, this operation updates that
+ frontend using the uploaded archive and starts a new deployment. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. If another deployment is running, the response preserves the frontend's current status
+ and exposes the queued deployment through `pending_deployment_id`.
+ Existing frontend traffic continues to use an available runtime while the new deployment builds
+ and provisions. Each deployment publishes its own static assets before the runtimes switch to its
+ build, and the live build's assets keep serving until the new deployment is live, so a page loaded
+ mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes
+ back on the build they were running, leaves the frontend `active` on the previous deployment, and
+ records the attempted deployment as failed. `degraded` means the runtime remains available but
+ edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one
+ deployment may run for a
+ given frontend, while independent frontends and projects can deploy concurrently.
+ For monorepos, provide `app_root` as a relative path from the uploaded archive root
+ to the Next.js app that should be built. Omit it for single-app archives.
+ Supported frontend environments are Next.js 15.x and 16.x with Node.js
+ 22.x or 24.x. The Node.js runtime is inferred from
+ `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x.
+ The selected Node.js family must also satisfy the installed Next.js package's
+ `engines.node` constraint. Volcano tests Next 15.5.24 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next
+ 16.3.3 (`>=20.9.0`).
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container images are
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`,
+ `PRO_FRONTEND_DEPLOYMENTS`).
+ Each project can contain up to 10,000 frontends regardless of plan.
+
+ Args:
+ id (UUID):
+ body (CreateFrontendBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Frontend]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendBody,
+
+) -> Error | Frontend | None:
+ """ Create a new frontend deployment
+
+ Creates and deploys a frontend for the project.
+ If a frontend with the same name already exists in the project, this operation updates that
+ frontend using the uploaded archive and starts a new deployment. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. If another deployment is running, the response preserves the frontend's current status
+ and exposes the queued deployment through `pending_deployment_id`.
+ Existing frontend traffic continues to use an available runtime while the new deployment builds
+ and provisions. Each deployment publishes its own static assets before the runtimes switch to its
+ build, and the live build's assets keep serving until the new deployment is live, so a page loaded
+ mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes
+ back on the build they were running, leaves the frontend `active` on the previous deployment, and
+ records the attempted deployment as failed. `degraded` means the runtime remains available but
+ edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one
+ deployment may run for a
+ given frontend, while independent frontends and projects can deploy concurrently.
+ For monorepos, provide `app_root` as a relative path from the uploaded archive root
+ to the Next.js app that should be built. Omit it for single-app archives.
+ Supported frontend environments are Next.js 15.x and 16.x with Node.js
+ 22.x or 24.x. The Node.js runtime is inferred from
+ `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x.
+ The selected Node.js family must also satisfy the installed Next.js package's
+ `engines.node` constraint. Volcano tests Next 15.5.24 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next
+ 16.3.3 (`>=20.9.0`).
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container images are
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`,
+ `PRO_FRONTEND_DEPLOYMENTS`).
+ Each project can contain up to 10,000 frontends regardless of plan.
+
+ Args:
+ id (UUID):
+ body (CreateFrontendBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Frontend
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendBody,
+
+) -> Response[Error | Frontend]:
+ """ Create a new frontend deployment
+
+ Creates and deploys a frontend for the project.
+ If a frontend with the same name already exists in the project, this operation updates that
+ frontend using the uploaded archive and starts a new deployment. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. If another deployment is running, the response preserves the frontend's current status
+ and exposes the queued deployment through `pending_deployment_id`.
+ Existing frontend traffic continues to use an available runtime while the new deployment builds
+ and provisions. Each deployment publishes its own static assets before the runtimes switch to its
+ build, and the live build's assets keep serving until the new deployment is live, so a page loaded
+ mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes
+ back on the build they were running, leaves the frontend `active` on the previous deployment, and
+ records the attempted deployment as failed. `degraded` means the runtime remains available but
+ edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one
+ deployment may run for a
+ given frontend, while independent frontends and projects can deploy concurrently.
+ For monorepos, provide `app_root` as a relative path from the uploaded archive root
+ to the Next.js app that should be built. Omit it for single-app archives.
+ Supported frontend environments are Next.js 15.x and 16.x with Node.js
+ 22.x or 24.x. The Node.js runtime is inferred from
+ `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x.
+ The selected Node.js family must also satisfy the installed Next.js package's
+ `engines.node` constraint. Volcano tests Next 15.5.24 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next
+ 16.3.3 (`>=20.9.0`).
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container images are
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`,
+ `PRO_FRONTEND_DEPLOYMENTS`).
+ Each project can contain up to 10,000 frontends regardless of plan.
+
+ Args:
+ id (UUID):
+ body (CreateFrontendBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Frontend]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendBody,
+
+) -> Error | Frontend | None:
+ """ Create a new frontend deployment
+
+ Creates and deploys a frontend for the project.
+ If a frontend with the same name already exists in the project, this operation updates that
+ frontend using the uploaded archive and starts a new deployment. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. If another deployment is running, the response preserves the frontend's current status
+ and exposes the queued deployment through `pending_deployment_id`.
+ Existing frontend traffic continues to use an available runtime while the new deployment builds
+ and provisions. Each deployment publishes its own static assets before the runtimes switch to its
+ build, and the live build's assets keep serving until the new deployment is live, so a page loaded
+ mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes
+ back on the build they were running, leaves the frontend `active` on the previous deployment, and
+ records the attempted deployment as failed. `degraded` means the runtime remains available but
+ edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one
+ deployment may run for a
+ given frontend, while independent frontends and projects can deploy concurrently.
+ For monorepos, provide `app_root` as a relative path from the uploaded archive root
+ to the Next.js app that should be built. Omit it for single-app archives.
+ Supported frontend environments are Next.js 15.x and 16.x with Node.js
+ 22.x or 24.x. The Node.js runtime is inferred from
+ `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x.
+ The selected Node.js family must also satisfy the installed Next.js package's
+ `engines.node` constraint. Volcano tests Next 15.5.24 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next
+ 16.3.3 (`>=20.9.0`).
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container images are
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`,
+ `PRO_FRONTEND_DEPLOYMENTS`).
+ Each project can contain up to 10,000 frontends regardless of plan.
+
+ Args:
+ id (UUID):
+ body (CreateFrontendBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Frontend
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/create_frontend_custom_domain.py b/src/volcano_sdk/_generated/api/frontends/create_frontend_custom_domain.py
new file mode 100644
index 00000000..0321f05a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/create_frontend_custom_domain.py
@@ -0,0 +1,278 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_frontend_custom_domain_request import CreateFrontendCustomDomainRequest
+from ...models.error import Error
+from ...models.frontend_custom_domain_response import FrontendCustomDomainResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ body: CreateFrontendCustomDomainRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/frontends/{frontend_id}/domain".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | FrontendCustomDomainResponse | None:
+ if response.status_code == 200:
+ response_200 = FrontendCustomDomainResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 201:
+ response_201 = FrontendCustomDomainResponse.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | FrontendCustomDomainResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendCustomDomainRequest,
+
+) -> Response[Error | FrontendCustomDomainResponse]:
+ """ Configure frontend custom domain (PRO)
+
+ Configures one custom domain for a frontend.
+ The default Volcano-generated frontend URL remains active.
+ Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ body (CreateFrontendCustomDomainRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FrontendCustomDomainResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendCustomDomainRequest,
+
+) -> Error | FrontendCustomDomainResponse | None:
+ """ Configure frontend custom domain (PRO)
+
+ Configures one custom domain for a frontend.
+ The default Volcano-generated frontend URL remains active.
+ Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ body (CreateFrontendCustomDomainRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FrontendCustomDomainResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendCustomDomainRequest,
+
+) -> Response[Error | FrontendCustomDomainResponse]:
+ """ Configure frontend custom domain (PRO)
+
+ Configures one custom domain for a frontend.
+ The default Volcano-generated frontend URL remains active.
+ Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ body (CreateFrontendCustomDomainRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FrontendCustomDomainResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFrontendCustomDomainRequest,
+
+) -> Error | FrontendCustomDomainResponse | None:
+ """ Configure frontend custom domain (PRO)
+
+ Configures one custom domain for a frontend.
+ The default Volcano-generated frontend URL remains active.
+ Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ body (CreateFrontendCustomDomainRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FrontendCustomDomainResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/delete_frontend.py b/src/volcano_sdk/_generated/api/frontends/delete_frontend.py
new file mode 100644
index 00000000..9f0dbd37
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/delete_frontend.py
@@ -0,0 +1,244 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/frontends/{frontend_id}".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 202:
+ response_202 = cast(Any, None)
+ return response_202
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a frontend
+
+ Schedules asynchronous frontend deletion. If another deployment is running, the frontend
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in frontend lists.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a frontend
+
+ Schedules asynchronous frontend deletion. If another deployment is running, the frontend
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in frontend lists.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a frontend
+
+ Schedules asynchronous frontend deletion. If another deployment is running, the frontend
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in frontend lists.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a frontend
+
+ Schedules asynchronous frontend deletion. If another deployment is running, the frontend
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in frontend lists.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/delete_frontend_custom_domain.py b/src/volcano_sdk/_generated/api/frontends/delete_frontend_custom_domain.py
new file mode 100644
index 00000000..f9fdfdfb
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/delete_frontend_custom_domain.py
@@ -0,0 +1,217 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/frontends/{frontend_id}/domain".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete frontend custom domain
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete frontend custom domain
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete frontend custom domain
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete frontend custom domain
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/get_frontend.py b/src/volcano_sdk/_generated/api/frontends/get_frontend.py
new file mode 100644
index 00000000..bdd0add5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/get_frontend.py
@@ -0,0 +1,221 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.frontend import Frontend
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/frontends/{frontend_id}".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Frontend | None:
+ if response.status_code == 200:
+ response_200 = Frontend.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Frontend]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Frontend]:
+ """ Get frontend details
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Frontend]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Frontend | None:
+ """ Get frontend details
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Frontend
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Frontend]:
+ """ Get frontend details
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Frontend]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Frontend | None:
+ """ Get frontend details
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Frontend
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/get_frontend_custom_domain.py b/src/volcano_sdk/_generated/api/frontends/get_frontend_custom_domain.py
new file mode 100644
index 00000000..a330d509
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/get_frontend_custom_domain.py
@@ -0,0 +1,234 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.frontend_custom_domain_response import FrontendCustomDomainResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/frontends/{frontend_id}/domain".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | FrontendCustomDomainResponse | None | None:
+ if response.status_code == 200:
+ def _parse_response_200(data: object) -> FrontendCustomDomainResponse | None:
+ if data is None:
+ return data
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ response_200_type_1 = FrontendCustomDomainResponse.from_dict(data)
+
+
+
+ return response_200_type_1
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(FrontendCustomDomainResponse | None, data)
+
+ response_200 = _parse_response_200(response.json())
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | FrontendCustomDomainResponse | None]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | FrontendCustomDomainResponse | None]:
+ """ Get frontend custom domain status
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FrontendCustomDomainResponse | None]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | FrontendCustomDomainResponse | None | None:
+ """ Get frontend custom domain status
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FrontendCustomDomainResponse | None
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | FrontendCustomDomainResponse | None]:
+ """ Get frontend custom domain status
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FrontendCustomDomainResponse | None]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | FrontendCustomDomainResponse | None | None:
+ """ Get frontend custom domain status
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FrontendCustomDomainResponse | None
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/get_frontend_usage_history.py b/src/volcano_sdk/_generated/api/frontends/get_frontend_usage_history.py
new file mode 100644
index 00000000..dcb5e689
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/get_frontend_usage_history.py
@@ -0,0 +1,283 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.frontend_usage_history_response import FrontendUsageHistoryResponse
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ days: int | Unset = 30,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["days"] = days
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/frontends/{frontend_id}/usage".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | FrontendUsageHistoryResponse | None:
+ if response.status_code == 200:
+ response_200 = FrontendUsageHistoryResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | FrontendUsageHistoryResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ days: int | Unset = 30,
+
+) -> Response[Error | FrontendUsageHistoryResponse]:
+ """ Per-day request and error counts for a single frontend
+
+ Returns a zero-filled daily series of request counts and 5xx
+ error counts for one frontend, oldest first. Each entry is one
+ UTC day; missing days (no traffic recorded) come back as
+ `requests: 0, errors: 0` so the response always has exactly
+ `days` entries.
+
+ Backs the Monitoring section on the Frontend detail page in
+ volcano-web. `days` defaults to 30 and is capped at 90 to keep
+ the (frontend_id, day) index scan bounded.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ days (int | Unset): Default: 30.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FrontendUsageHistoryResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+days=days,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ days: int | Unset = 30,
+
+) -> Error | FrontendUsageHistoryResponse | None:
+ """ Per-day request and error counts for a single frontend
+
+ Returns a zero-filled daily series of request counts and 5xx
+ error counts for one frontend, oldest first. Each entry is one
+ UTC day; missing days (no traffic recorded) come back as
+ `requests: 0, errors: 0` so the response always has exactly
+ `days` entries.
+
+ Backs the Monitoring section on the Frontend detail page in
+ volcano-web. `days` defaults to 30 and is capped at 90 to keep
+ the (frontend_id, day) index scan bounded.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ days (int | Unset): Default: 30.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FrontendUsageHistoryResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+days=days,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ days: int | Unset = 30,
+
+) -> Response[Error | FrontendUsageHistoryResponse]:
+ """ Per-day request and error counts for a single frontend
+
+ Returns a zero-filled daily series of request counts and 5xx
+ error counts for one frontend, oldest first. Each entry is one
+ UTC day; missing days (no traffic recorded) come back as
+ `requests: 0, errors: 0` so the response always has exactly
+ `days` entries.
+
+ Backs the Monitoring section on the Frontend detail page in
+ volcano-web. `days` defaults to 30 and is capped at 90 to keep
+ the (frontend_id, day) index scan bounded.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ days (int | Unset): Default: 30.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FrontendUsageHistoryResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+days=days,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ days: int | Unset = 30,
+
+) -> Error | FrontendUsageHistoryResponse | None:
+ """ Per-day request and error counts for a single frontend
+
+ Returns a zero-filled daily series of request counts and 5xx
+ error counts for one frontend, oldest first. Each entry is one
+ UTC day; missing days (no traffic recorded) come back as
+ `requests: 0, errors: 0` so the response always has exactly
+ `days` entries.
+
+ Backs the Monitoring section on the Frontend detail page in
+ volcano-web. `days` defaults to 30 and is capped at 90 to keep
+ the (frontend_id, day) index scan bounded.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ days (int | Unset): Default: 30.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FrontendUsageHistoryResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+days=days,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/list_frontend_deployments.py b/src/volcano_sdk/_generated/api/frontends/list_frontend_deployments.py
new file mode 100644
index 00000000..8a1699da
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/list_frontend_deployments.py
@@ -0,0 +1,258 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.paginated_frontend_deployments import PaginatedFrontendDeployments
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/frontends/{frontend_id}/deployments".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedFrontendDeployments | None:
+ if response.status_code == 200:
+ response_200 = PaginatedFrontendDeployments.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedFrontendDeployments]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Response[Error | PaginatedFrontendDeployments]:
+ """ List frontend deployments
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFrontendDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+page=page,
+limit=limit,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Error | PaginatedFrontendDeployments | None:
+ """ List frontend deployments
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFrontendDeployments
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+page=page,
+limit=limit,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Response[Error | PaginatedFrontendDeployments]:
+ """ List frontend deployments
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFrontendDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+page=page,
+limit=limit,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Error | PaginatedFrontendDeployments | None:
+ """ List frontend deployments
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFrontendDeployments
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+page=page,
+limit=limit,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/list_frontends.py b/src/volcano_sdk/_generated/api/frontends/list_frontends.py
new file mode 100644
index 00000000..8a539e33
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/list_frontends.py
@@ -0,0 +1,329 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.paginated_frontends import PaginatedFrontends
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/frontends".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedFrontends | None:
+ if response.status_code == 200:
+ response_200 = PaginatedFrontends.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedFrontends]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedFrontends]:
+ """ List all frontends in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFrontends]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedFrontends | None:
+ """ List all frontends in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFrontends
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedFrontends]:
+ """ List all frontends in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFrontends]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedFrontends | None:
+ """ List all frontends in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
+ returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFrontends
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/list_project_custom_domains.py b/src/volcano_sdk/_generated/api/frontends/list_project_custom_domains.py
new file mode 100644
index 00000000..51a7b0b4
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/list_project_custom_domains.py
@@ -0,0 +1,318 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.paginated_project_custom_domains import PaginatedProjectCustomDomains
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/domains".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedProjectCustomDomains | None:
+ if response.status_code == 200:
+ response_200 = PaginatedProjectCustomDomains.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedProjectCustomDomains]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedProjectCustomDomains]:
+ r""" List all custom domains in a project
+
+ Project-scoped custom-domain list. Returns every active custom
+ domain across every frontend in the project (excludes soft-deleted
+ rows). Each item inlines the linked frontend's id and name so the
+ UI does not need a second fetch to render the \"Linked to\" column.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjectCustomDomains]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedProjectCustomDomains | None:
+ r""" List all custom domains in a project
+
+ Project-scoped custom-domain list. Returns every active custom
+ domain across every frontend in the project (excludes soft-deleted
+ rows). Each item inlines the linked frontend's id and name so the
+ UI does not need a second fetch to render the \"Linked to\" column.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjectCustomDomains
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedProjectCustomDomains]:
+ r""" List all custom domains in a project
+
+ Project-scoped custom-domain list. Returns every active custom
+ domain across every frontend in the project (excludes soft-deleted
+ rows). Each item inlines the linked frontend's id and name so the
+ UI does not need a second fetch to render the \"Linked to\" column.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjectCustomDomains]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedProjectCustomDomains | None:
+ r""" List all custom domains in a project
+
+ Project-scoped custom-domain list. Returns every active custom
+ domain across every frontend in the project (excludes soft-deleted
+ rows). Each item inlines the linked frontend's id and name so the
+ UI does not need a second fetch to render the \"Linked to\" column.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjectCustomDomains
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/frontends/redeploy_frontend.py b/src/volcano_sdk/_generated/api/frontends/redeploy_frontend.py
new file mode 100644
index 00000000..349aad61
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/frontends/redeploy_frontend.py
@@ -0,0 +1,267 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.frontend import Frontend
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ frontend_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/frontends/{frontend_id}/redeploy".format(id=quote(str(id), safe=""),frontend_id=quote(str(frontend_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Frontend | None:
+ if response.status_code == 200:
+ response_200 = Frontend.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Frontend]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Frontend]:
+ """ Redeploy frontend using latest uploaded artifact
+
+ Starts a new frontend workflow using the latest stored artifact. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. An overlapping deployment preserves the frontend's current status, is exposed through
+ `pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its
+ published static assets remain available during provisioning, and a failed redeploy restores the
+ regional runtimes to that build and keeps it serving while the attempted deployment is recorded as
+ failed.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Frontend]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Frontend | None:
+ """ Redeploy frontend using latest uploaded artifact
+
+ Starts a new frontend workflow using the latest stored artifact. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. An overlapping deployment preserves the frontend's current status, is exposed through
+ `pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its
+ published static assets remain available during provisioning, and a failed redeploy restores the
+ regional runtimes to that build and keeps it serving while the attempted deployment is recorded as
+ failed.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Frontend
+ """
+
+
+ return sync_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Frontend]:
+ """ Redeploy frontend using latest uploaded artifact
+
+ Starts a new frontend workflow using the latest stored artifact. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. An overlapping deployment preserves the frontend's current status, is exposed through
+ `pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its
+ published static assets remain available during provisioning, and a failed redeploy restores the
+ regional runtimes to that build and keeps it serving while the attempted deployment is recorded as
+ failed.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Frontend]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+frontend_id=frontend_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ frontend_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Frontend | None:
+ """ Redeploy frontend using latest uploaded artifact
+
+ Starts a new frontend workflow using the latest stored artifact. A deployment that starts
+ immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
+ `failed`. An overlapping deployment preserves the frontend's current status, is exposed through
+ `pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its
+ published static assets remain available during provisioning, and a failed redeploy restores the
+ regional runtimes to that build and keeps it serving while the attempted deployment is recorded as
+ failed.
+
+ Args:
+ id (UUID):
+ frontend_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Frontend
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+frontend_id=frontend_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/__init__.py b/src/volcano_sdk/_generated/api/functions/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/functions/create_function.py b/src/volcano_sdk/_generated/api/functions/create_function.py
new file mode 100644
index 00000000..be771b06
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/create_function.py
@@ -0,0 +1,320 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_function_body import CreateFunctionBody
+from ...models.error import Error
+from ...models.function import Function
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateFunctionBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/functions".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["files"] = body.to_multipart()
+
+ headers["Content-Type"] = "multipart/form-data; boundary=+++"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Function | None:
+ if response.status_code == 200:
+ response_200 = Function.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 201:
+ response_201 = Function.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Function]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionBody,
+
+) -> Response[Error | Function]:
+ """ Create or update function code
+
+ Upload a serverless function source bundle. Direct API clients may send the function code
+ as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz
+ source archive.
+ Cloud deploys should include source files and dependency manifests/lockfiles, not installed
+ dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the
+ function compile build.
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container image is
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ Uploaded source archives cannot contain symlink entries. Safe symlinks created during
+ the cloud build are materialized before publish.
+ Volcano builds and deploys the function asynchronously after upload. A deployment that starts
+ immediately returns a Function resource with `status: provisioning`, then transitions to
+ `active` or `failed`. If another deployment is running, the response preserves the resource's
+ current status and exposes the queued deployment through `pending_deployment_id`.
+ Existing function traffic continues to use the last known-good runtime during an update. A failed
+ update keeps that runtime available and records the attempted deployment as failed.
+ Only one deployment runs for a given function. A newer request supersedes any queued request
+ and starts after the running deployment. Different functions and projects deploy concurrently.
+ If a function with the same name already exists in the project, this operation updates that
+ function's runtime, handler, and source bundle and returns `200 OK`.
+ Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Function]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionBody,
+
+) -> Error | Function | None:
+ """ Create or update function code
+
+ Upload a serverless function source bundle. Direct API clients may send the function code
+ as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz
+ source archive.
+ Cloud deploys should include source files and dependency manifests/lockfiles, not installed
+ dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the
+ function compile build.
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container image is
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ Uploaded source archives cannot contain symlink entries. Safe symlinks created during
+ the cloud build are materialized before publish.
+ Volcano builds and deploys the function asynchronously after upload. A deployment that starts
+ immediately returns a Function resource with `status: provisioning`, then transitions to
+ `active` or `failed`. If another deployment is running, the response preserves the resource's
+ current status and exposes the queued deployment through `pending_deployment_id`.
+ Existing function traffic continues to use the last known-good runtime during an update. A failed
+ update keeps that runtime available and records the attempted deployment as failed.
+ Only one deployment runs for a given function. A newer request supersedes any queued request
+ and starts after the running deployment. Different functions and projects deploy concurrently.
+ If a function with the same name already exists in the project, this operation updates that
+ function's runtime, handler, and source bundle and returns `200 OK`.
+ Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Function
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionBody,
+
+) -> Response[Error | Function]:
+ """ Create or update function code
+
+ Upload a serverless function source bundle. Direct API clients may send the function code
+ as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz
+ source archive.
+ Cloud deploys should include source files and dependency manifests/lockfiles, not installed
+ dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the
+ function compile build.
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container image is
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ Uploaded source archives cannot contain symlink entries. Safe symlinks created during
+ the cloud build are materialized before publish.
+ Volcano builds and deploys the function asynchronously after upload. A deployment that starts
+ immediately returns a Function resource with `status: provisioning`, then transitions to
+ `active` or `failed`. If another deployment is running, the response preserves the resource's
+ current status and exposes the queued deployment through `pending_deployment_id`.
+ Existing function traffic continues to use the last known-good runtime during an update. A failed
+ update keeps that runtime available and records the attempted deployment as failed.
+ Only one deployment runs for a given function. A newer request supersedes any queued request
+ and starts after the running deployment. Different functions and projects deploy concurrently.
+ If a function with the same name already exists in the project, this operation updates that
+ function's runtime, handler, and source bundle and returns `200 OK`.
+ Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Function]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionBody,
+
+) -> Error | Function | None:
+ """ Create or update function code
+
+ Upload a serverless function source bundle. Direct API clients may send the function code
+ as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz
+ source archive.
+ Cloud deploys should include source files and dependency manifests/lockfiles, not installed
+ dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the
+ function compile build.
+ Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
+ does not apply its own source archive size limit. After the final container image is
+ built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
+ Uploaded source archives cannot contain symlink entries. Safe symlinks created during
+ the cloud build are materialized before publish.
+ Volcano builds and deploys the function asynchronously after upload. A deployment that starts
+ immediately returns a Function resource with `status: provisioning`, then transitions to
+ `active` or `failed`. If another deployment is running, the response preserves the resource's
+ current status and exposes the queued deployment through `pending_deployment_id`.
+ Existing function traffic continues to use the last known-good runtime during an update. A failed
+ update keeps that runtime available and records the attempted deployment as failed.
+ Only one deployment runs for a given function. A newer request supersedes any queued request
+ and starts after the running deployment. Different functions and projects deploy concurrently.
+ If a function with the same name already exists in the project, this operation updates that
+ function's runtime, handler, and source bundle and returns `200 OK`.
+ Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Function
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/create_function_scheduler.py b/src/volcano_sdk/_generated/api/functions/create_function_scheduler.py
new file mode 100644
index 00000000..223ee1ba
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/create_function_scheduler.py
@@ -0,0 +1,225 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_function_scheduler_request import CreateFunctionSchedulerRequest
+from ...models.error import Error
+from ...models.function_scheduler import FunctionScheduler
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+ *,
+ body: CreateFunctionSchedulerRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/functions/{function_id}/schedulers".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | FunctionScheduler | None:
+ if response.status_code == 201:
+ response_201 = FunctionScheduler.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | FunctionScheduler]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionSchedulerRequest,
+
+) -> Response[Error | FunctionScheduler]:
+ """ Create a scheduler for a function
+
+ Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's
+ deployed regions.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (CreateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FunctionScheduler]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionSchedulerRequest,
+
+) -> Error | FunctionScheduler | None:
+ """ Create a scheduler for a function
+
+ Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's
+ deployed regions.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (CreateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FunctionScheduler
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionSchedulerRequest,
+
+) -> Response[Error | FunctionScheduler]:
+ """ Create a scheduler for a function
+
+ Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's
+ deployed regions.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (CreateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FunctionScheduler]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionSchedulerRequest,
+
+) -> Error | FunctionScheduler | None:
+ """ Create a scheduler for a function
+
+ Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's
+ deployed regions.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (CreateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FunctionScheduler
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/create_functions_batch.py b/src/volcano_sdk/_generated/api/functions/create_functions_batch.py
new file mode 100644
index 00000000..e549b188
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/create_functions_batch.py
@@ -0,0 +1,271 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.batch_function_deploy_response import BatchFunctionDeployResponse
+from ...models.create_functions_batch_body import CreateFunctionsBatchBody
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateFunctionsBatchBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/functions/batch".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["files"] = body.to_multipart()
+
+ headers["Content-Type"] = "multipart/form-data; boundary=+++"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> BatchFunctionDeployResponse | Error | None:
+ if response.status_code == 202:
+ response_202 = BatchFunctionDeployResponse.from_dict(response.json())
+
+
+
+ return response_202
+
+ if response.status_code == 207:
+ response_207 = BatchFunctionDeployResponse.from_dict(response.json())
+
+
+
+ return response_207
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[BatchFunctionDeployResponse | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionsBatchBody,
+
+) -> Response[BatchFunctionDeployResponse | Error]:
+ """ Deploy multiple functions in one request
+
+ Upload multiple function source archives in one multipart request. Each archive should contain
+ source files
+ plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads
+ are
+ accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB`
+ for each uploaded and normalized source archive. The server records a shared
+ deployment batch ID for the resulting function deployments. Each function deployment runs its own
+ compile/publish workflow concurrently, and each publish build enforces
+ `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB`
+ for the final container image.
+ One batch request can include up to 100 functions. Submit multiple batch requests for larger
+ projects.
+ If one function fails before its workflow starts, already-started function deployments are left
+ running and the failed function is reported in the `failed` array. Failed new functions are deleted;
+ failed updates are rolled back to their previous metadata/status where possible.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionsBatchBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[BatchFunctionDeployResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionsBatchBody,
+
+) -> BatchFunctionDeployResponse | Error | None:
+ """ Deploy multiple functions in one request
+
+ Upload multiple function source archives in one multipart request. Each archive should contain
+ source files
+ plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads
+ are
+ accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB`
+ for each uploaded and normalized source archive. The server records a shared
+ deployment batch ID for the resulting function deployments. Each function deployment runs its own
+ compile/publish workflow concurrently, and each publish build enforces
+ `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB`
+ for the final container image.
+ One batch request can include up to 100 functions. Submit multiple batch requests for larger
+ projects.
+ If one function fails before its workflow starts, already-started function deployments are left
+ running and the failed function is reported in the `failed` array. Failed new functions are deleted;
+ failed updates are rolled back to their previous metadata/status where possible.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionsBatchBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ BatchFunctionDeployResponse | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionsBatchBody,
+
+) -> Response[BatchFunctionDeployResponse | Error]:
+ """ Deploy multiple functions in one request
+
+ Upload multiple function source archives in one multipart request. Each archive should contain
+ source files
+ plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads
+ are
+ accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB`
+ for each uploaded and normalized source archive. The server records a shared
+ deployment batch ID for the resulting function deployments. Each function deployment runs its own
+ compile/publish workflow concurrently, and each publish build enforces
+ `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB`
+ for the final container image.
+ One batch request can include up to 100 functions. Submit multiple batch requests for larger
+ projects.
+ If one function fails before its workflow starts, already-started function deployments are left
+ running and the failed function is reported in the `failed` array. Failed new functions are deleted;
+ failed updates are rolled back to their previous metadata/status where possible.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionsBatchBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[BatchFunctionDeployResponse | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateFunctionsBatchBody,
+
+) -> BatchFunctionDeployResponse | Error | None:
+ """ Deploy multiple functions in one request
+
+ Upload multiple function source archives in one multipart request. Each archive should contain
+ source files
+ plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads
+ are
+ accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB`
+ for each uploaded and normalized source archive. The server records a shared
+ deployment batch ID for the resulting function deployments. Each function deployment runs its own
+ compile/publish workflow concurrently, and each publish build enforces
+ `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB`
+ for the final container image.
+ One batch request can include up to 100 functions. Submit multiple batch requests for larger
+ projects.
+ If one function fails before its workflow starts, already-started function deployments are left
+ running and the failed function is reported in the `failed` array. Failed new functions are deleted;
+ failed updates are rolled back to their previous metadata/status where possible.
+
+ Args:
+ id (UUID):
+ body (CreateFunctionsBatchBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ BatchFunctionDeployResponse | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/delete_function.py b/src/volcano_sdk/_generated/api/functions/delete_function.py
new file mode 100644
index 00000000..a5e84a55
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/delete_function.py
@@ -0,0 +1,209 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/functions/{function_id}".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 202:
+ response_202 = cast(Any, None)
+ return response_202
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a function
+
+ Schedules asynchronous function deletion. If another deployment is running, the function
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in function lists.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a function
+
+ Schedules asynchronous function deletion. If another deployment is running, the function
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in function lists.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a function
+
+ Schedules asynchronous function deletion. If another deployment is running, the function
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in function lists.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a function
+
+ Schedules asynchronous function deletion. If another deployment is running, the function
+ preserves its current status and exposes the queued deletion through `pending_deployment_id`.
+ Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
+ longer appears in function lists.
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/delete_function_scheduler.py b/src/volcano_sdk/_generated/api/functions/delete_function_scheduler.py
new file mode 100644
index 00000000..f932ba95
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/delete_function_scheduler.py
@@ -0,0 +1,130 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/functions/{function_id}/schedulers/{scheduler_id}".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),scheduler_id=quote(str(scheduler_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 204:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/functions/get_function.py b/src/volcano_sdk/_generated/api/functions/get_function.py
new file mode 100644
index 00000000..0e883048
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/get_function.py
@@ -0,0 +1,193 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.function import Function
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/functions/{function_id}".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Function | None:
+ if response.status_code == 200:
+ response_200 = Function.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Function]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Function]:
+ """ Get function by ID
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Function]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Function | None:
+ """ Get function by ID
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Function
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Function]:
+ """ Get function by ID
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Function]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Function | None:
+ """ Get function by ID
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Function
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/get_function_scheduler.py b/src/volcano_sdk/_generated/api/functions/get_function_scheduler.py
new file mode 100644
index 00000000..306310ca
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/get_function_scheduler.py
@@ -0,0 +1,198 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.function_scheduler import FunctionScheduler
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/functions/{function_id}/schedulers/{scheduler_id}".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),scheduler_id=quote(str(scheduler_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> FunctionScheduler | None:
+ if response.status_code == 200:
+ response_200 = FunctionScheduler.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[FunctionScheduler]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[FunctionScheduler]:
+ """ Get a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionScheduler]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> FunctionScheduler | None:
+ """ Get a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionScheduler
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[FunctionScheduler]:
+ """ Get a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionScheduler]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> FunctionScheduler | None:
+ """ Get a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionScheduler
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/invoke_function.py b/src/volcano_sdk/_generated/api/functions/invoke_function.py
new file mode 100644
index 00000000..a7db9b67
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/invoke_function.py
@@ -0,0 +1,357 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.function_invocation_request import FunctionInvocationRequest
+from ...models.function_invocation_response import FunctionInvocationResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ function_id: UUID,
+ *,
+ body: FunctionInvocationRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/functions/{function_id}/invoke".format(function_id=quote(str(function_id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | FunctionInvocationResponse:
+ if response.status_code == 200:
+ response_200 = FunctionInvocationResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ response_default = FunctionInvocationResponse.from_dict(response.json())
+
+
+
+ return response_default
+
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | FunctionInvocationResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: FunctionInvocationRequest,
+
+) -> Response[Error | FunctionInvocationResponse]:
+ r""" Invoke a function
+
+ Invoke a serverless function.
+
+ **With Service Key** (admin/background operations):
+ - Use for background jobs, webhooks, cron, admin operations
+ - Function receives payload only (no user context)
+ - Database queries bypass RLS (admin access)
+
+ **With Auth User Token** (user-facing):
+ - Use for user-initiated actions
+ - Function receives payload + `__volcano_auth` context:
+ ```javascript
+ {
+ user_id: \"uuid\",
+ email: \"user@example.com\",
+ project_id: \"uuid\",
+ role: \"authenticated\" or \"anonymous\"
+ }
+ ```
+ - Database queries enforce RLS (user-scoped data)
+
+ **With Anon Key** (public function only):
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+ - Function receives payload only (no `__volcano_auth`)
+
+ **Transport and CORS:**
+ - Direct invocation endpoint is intended for `http://api./functions/{functionId}/invoke`
+ - DNS invocation endpoint is `https://{functionId}.functions./`
+ - CORS preflight for invocation allows only `POST, OPTIONS`
+
+ Args:
+ function_id (UUID):
+ body (FunctionInvocationRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FunctionInvocationResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ function_id=function_id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: FunctionInvocationRequest,
+
+) -> Error | FunctionInvocationResponse | None:
+ r""" Invoke a function
+
+ Invoke a serverless function.
+
+ **With Service Key** (admin/background operations):
+ - Use for background jobs, webhooks, cron, admin operations
+ - Function receives payload only (no user context)
+ - Database queries bypass RLS (admin access)
+
+ **With Auth User Token** (user-facing):
+ - Use for user-initiated actions
+ - Function receives payload + `__volcano_auth` context:
+ ```javascript
+ {
+ user_id: \"uuid\",
+ email: \"user@example.com\",
+ project_id: \"uuid\",
+ role: \"authenticated\" or \"anonymous\"
+ }
+ ```
+ - Database queries enforce RLS (user-scoped data)
+
+ **With Anon Key** (public function only):
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+ - Function receives payload only (no `__volcano_auth`)
+
+ **Transport and CORS:**
+ - Direct invocation endpoint is intended for `http://api./functions/{functionId}/invoke`
+ - DNS invocation endpoint is `https://{functionId}.functions./`
+ - CORS preflight for invocation allows only `POST, OPTIONS`
+
+ Args:
+ function_id (UUID):
+ body (FunctionInvocationRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FunctionInvocationResponse
+ """
+
+
+ return sync_detailed(
+ function_id=function_id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: FunctionInvocationRequest,
+
+) -> Response[Error | FunctionInvocationResponse]:
+ r""" Invoke a function
+
+ Invoke a serverless function.
+
+ **With Service Key** (admin/background operations):
+ - Use for background jobs, webhooks, cron, admin operations
+ - Function receives payload only (no user context)
+ - Database queries bypass RLS (admin access)
+
+ **With Auth User Token** (user-facing):
+ - Use for user-initiated actions
+ - Function receives payload + `__volcano_auth` context:
+ ```javascript
+ {
+ user_id: \"uuid\",
+ email: \"user@example.com\",
+ project_id: \"uuid\",
+ role: \"authenticated\" or \"anonymous\"
+ }
+ ```
+ - Database queries enforce RLS (user-scoped data)
+
+ **With Anon Key** (public function only):
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+ - Function receives payload only (no `__volcano_auth`)
+
+ **Transport and CORS:**
+ - Direct invocation endpoint is intended for `http://api./functions/{functionId}/invoke`
+ - DNS invocation endpoint is `https://{functionId}.functions./`
+ - CORS preflight for invocation allows only `POST, OPTIONS`
+
+ Args:
+ function_id (UUID):
+ body (FunctionInvocationRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | FunctionInvocationResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ function_id=function_id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: FunctionInvocationRequest,
+
+) -> Error | FunctionInvocationResponse | None:
+ r""" Invoke a function
+
+ Invoke a serverless function.
+
+ **With Service Key** (admin/background operations):
+ - Use for background jobs, webhooks, cron, admin operations
+ - Function receives payload only (no user context)
+ - Database queries bypass RLS (admin access)
+
+ **With Auth User Token** (user-facing):
+ - Use for user-initiated actions
+ - Function receives payload + `__volcano_auth` context:
+ ```javascript
+ {
+ user_id: \"uuid\",
+ email: \"user@example.com\",
+ project_id: \"uuid\",
+ role: \"authenticated\" or \"anonymous\"
+ }
+ ```
+ - Database queries enforce RLS (user-scoped data)
+
+ **With Anon Key** (public function only):
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+ - Function receives payload only (no `__volcano_auth`)
+
+ **Transport and CORS:**
+ - Direct invocation endpoint is intended for `http://api./functions/{functionId}/invoke`
+ - DNS invocation endpoint is `https://{functionId}.functions./`
+ - CORS preflight for invocation allows only `POST, OPTIONS`
+
+ Args:
+ function_id (UUID):
+ body (FunctionInvocationRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | FunctionInvocationResponse
+ """
+
+
+ return (await asyncio_detailed(
+ function_id=function_id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/list_function_deployments.py b/src/volcano_sdk/_generated/api/functions/list_function_deployments.py
new file mode 100644
index 00000000..4153fb99
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/list_function_deployments.py
@@ -0,0 +1,230 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.paginated_function_deployments import PaginatedFunctionDeployments
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/functions/{function_id}/deployments".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedFunctionDeployments | None:
+ if response.status_code == 200:
+ response_200 = PaginatedFunctionDeployments.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedFunctionDeployments]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Response[Error | PaginatedFunctionDeployments]:
+ """ List function deployments
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFunctionDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+page=page,
+limit=limit,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Error | PaginatedFunctionDeployments | None:
+ """ List function deployments
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFunctionDeployments
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+page=page,
+limit=limit,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Response[Error | PaginatedFunctionDeployments]:
+ """ List function deployments
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFunctionDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+page=page,
+limit=limit,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+
+) -> Error | PaginatedFunctionDeployments | None:
+ """ List function deployments
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFunctionDeployments
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+page=page,
+limit=limit,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/list_function_regions.py b/src/volcano_sdk/_generated/api/functions/list_function_regions.py
new file mode 100644
index 00000000..a829fd9c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/list_function_regions.py
@@ -0,0 +1,171 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.function_region import FunctionRegion
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/functions/regions",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> list[FunctionRegion] | None:
+ if response.status_code == 200:
+ response_200 = []
+ _response_200 = response.json()
+ for response_200_item_data in (_response_200):
+ response_200_item = FunctionRegion.from_dict(response_200_item_data)
+
+
+
+ response_200.append(response_200_item)
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[list[FunctionRegion]]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[list[FunctionRegion]]:
+ """ List available regions for function deployment
+
+ Returns the configured regions where functions can be deployed, each annotated
+ with a human-readable label and country flag emoji for use in UI pickers.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[FunctionRegion]]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> list[FunctionRegion] | None:
+ """ List available regions for function deployment
+
+ Returns the configured regions where functions can be deployed, each annotated
+ with a human-readable label and country flag emoji for use in UI pickers.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[FunctionRegion]
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[list[FunctionRegion]]:
+ """ List available regions for function deployment
+
+ Returns the configured regions where functions can be deployed, each annotated
+ with a human-readable label and country flag emoji for use in UI pickers.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[FunctionRegion]]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> list[FunctionRegion] | None:
+ """ List available regions for function deployment
+
+ Returns the configured regions where functions can be deployed, each annotated
+ with a human-readable label and country flag emoji for use in UI pickers.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[FunctionRegion]
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/list_function_runtimes.py b/src/volcano_sdk/_generated/api/functions/list_function_runtimes.py
new file mode 100644
index 00000000..a7e77d4d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/list_function_runtimes.py
@@ -0,0 +1,166 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.function_runtimes_response import FunctionRuntimesResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/functions/runtimes",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> FunctionRuntimesResponse | None:
+ if response.status_code == 200:
+ response_200 = FunctionRuntimesResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[FunctionRuntimesResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[FunctionRuntimesResponse]:
+ """ List supported function runtimes
+
+ Returns the public function runtime catalog used by CLI clients to select supported runtimes,
+ language defaults, and local source packaging metadata for deployments.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionRuntimesResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> FunctionRuntimesResponse | None:
+ """ List supported function runtimes
+
+ Returns the public function runtime catalog used by CLI clients to select supported runtimes,
+ language defaults, and local source packaging metadata for deployments.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionRuntimesResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[FunctionRuntimesResponse]:
+ """ List supported function runtimes
+
+ Returns the public function runtime catalog used by CLI clients to select supported runtimes,
+ language defaults, and local source packaging metadata for deployments.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionRuntimesResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> FunctionRuntimesResponse | None:
+ """ List supported function runtimes
+
+ Returns the public function runtime catalog used by CLI clients to select supported runtimes,
+ language defaults, and local source packaging metadata for deployments.
+ This is a public endpoint that doesn't require authentication.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionRuntimesResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/list_function_schedulers.py b/src/volcano_sdk/_generated/api/functions/list_function_schedulers.py
new file mode 100644
index 00000000..8a99825a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/list_function_schedulers.py
@@ -0,0 +1,185 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.function_scheduler_list_response import FunctionSchedulerListResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/functions/{function_id}/schedulers".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> FunctionSchedulerListResponse | None:
+ if response.status_code == 200:
+ response_200 = FunctionSchedulerListResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[FunctionSchedulerListResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[FunctionSchedulerListResponse]:
+ """ List schedulers for a function
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionSchedulerListResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> FunctionSchedulerListResponse | None:
+ """ List schedulers for a function
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionSchedulerListResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[FunctionSchedulerListResponse]:
+ """ List schedulers for a function
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionSchedulerListResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> FunctionSchedulerListResponse | None:
+ """ List schedulers for a function
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionSchedulerListResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/list_functions.py b/src/volcano_sdk/_generated/api/functions/list_functions.py
new file mode 100644
index 00000000..28eac2f2
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/list_functions.py
@@ -0,0 +1,301 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.paginated_functions import PaginatedFunctions
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/functions".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedFunctions | None:
+ if response.status_code == 200:
+ response_200 = PaginatedFunctions.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedFunctions]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedFunctions]:
+ """ List all functions in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page`
+ and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFunctions]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedFunctions | None:
+ """ List all functions in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page`
+ and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFunctions
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedFunctions]:
+ """ List all functions in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page`
+ and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedFunctions]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedFunctions | None:
+ """ List all functions in a project
+
+ Supports two mutually exclusive pagination modes. Offset mode uses `page`
+ and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
+ `limit`, supports `search` (case-insensitive name match), and returns
+ `next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page`
+ and `search`) returns 400.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedFunctions
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/list_project_schedulers.py b/src/volcano_sdk/_generated/api/functions/list_project_schedulers.py
new file mode 100644
index 00000000..1086c253
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/list_project_schedulers.py
@@ -0,0 +1,289 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.function_scheduler_list_response import FunctionSchedulerListResponse
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/schedulers".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> FunctionSchedulerListResponse | None:
+ if response.status_code == 200:
+ response_200 = FunctionSchedulerListResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[FunctionSchedulerListResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[FunctionSchedulerListResponse]:
+ """ List every function scheduler in a project
+
+ Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`.
+ Returns schedulers across all functions in the project, ordered by
+ creation time descending, with standard page/limit pagination so
+ clients don't have to fan out one request per function.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionSchedulerListResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> FunctionSchedulerListResponse | None:
+ """ List every function scheduler in a project
+
+ Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`.
+ Returns schedulers across all functions in the project, ordered by
+ creation time descending, with standard page/limit pagination so
+ clients don't have to fan out one request per function.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionSchedulerListResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[FunctionSchedulerListResponse]:
+ """ List every function scheduler in a project
+
+ Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`.
+ Returns schedulers across all functions in the project, ordered by
+ creation time descending, with standard page/limit pagination so
+ clients don't have to fan out one request per function.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionSchedulerListResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> FunctionSchedulerListResponse | None:
+ """ List every function scheduler in a project
+
+ Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`.
+ Returns schedulers across all functions in the project, ordered by
+ creation time descending, with standard page/limit pagination so
+ clients don't have to fan out one request per function.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionSchedulerListResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/resolve_function_for_invocation.py b/src/volcano_sdk/_generated/api/functions/resolve_function_for_invocation.py
new file mode 100644
index 00000000..9785bcac
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/resolve_function_for_invocation.py
@@ -0,0 +1,264 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.resolve_function_response import ResolveFunctionResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["name"] = name
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/functions/resolve",
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ResolveFunctionResponse | None:
+ if response.status_code == 200:
+ response_200 = ResolveFunctionResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ResolveFunctionResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ name: str,
+
+) -> Response[Error | ResolveFunctionResponse]:
+ """ Resolve function name for invocation
+
+ Resolves a DNS-safe function name to its function ID within the caller's project.
+
+ SDKs use this endpoint internally to invoke by function name while routing by function ID.
+
+ **With Service Key**:
+ - Allowed
+
+ **With Auth User Token**:
+ - Allowed
+
+ **With Anon Key**:
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+
+ Args:
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ResolveFunctionResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ name=name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ name: str,
+
+) -> Error | ResolveFunctionResponse | None:
+ """ Resolve function name for invocation
+
+ Resolves a DNS-safe function name to its function ID within the caller's project.
+
+ SDKs use this endpoint internally to invoke by function name while routing by function ID.
+
+ **With Service Key**:
+ - Allowed
+
+ **With Auth User Token**:
+ - Allowed
+
+ **With Anon Key**:
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+
+ Args:
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ResolveFunctionResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+name=name,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ name: str,
+
+) -> Response[Error | ResolveFunctionResponse]:
+ """ Resolve function name for invocation
+
+ Resolves a DNS-safe function name to its function ID within the caller's project.
+
+ SDKs use this endpoint internally to invoke by function name while routing by function ID.
+
+ **With Service Key**:
+ - Allowed
+
+ **With Auth User Token**:
+ - Allowed
+
+ **With Anon Key**:
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+
+ Args:
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ResolveFunctionResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ name=name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ name: str,
+
+) -> Error | ResolveFunctionResponse | None:
+ """ Resolve function name for invocation
+
+ Resolves a DNS-safe function name to its function ID within the caller's project.
+
+ SDKs use this endpoint internally to invoke by function name while routing by function ID.
+
+ **With Service Key**:
+ - Allowed
+
+ **With Auth User Token**:
+ - Allowed
+
+ **With Anon Key**:
+ - Requires anon key permission: `functions.invoke`
+ - Function must have `is_public: true`
+
+ Args:
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ResolveFunctionResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+name=name,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/update_function.py b/src/volcano_sdk/_generated/api/functions/update_function.py
new file mode 100644
index 00000000..c7b4b2f5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/update_function.py
@@ -0,0 +1,220 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.function import Function
+from ...models.update_function_request import UpdateFunctionRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+ *,
+ body: UpdateFunctionRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/projects/{id}/functions/{function_id}".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Function | None:
+ if response.status_code == 200:
+ response_200 = Function.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Function]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionRequest,
+
+) -> Response[Error | Function]:
+ """ Update function settings
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (UpdateFunctionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Function]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionRequest,
+
+) -> Error | Function | None:
+ """ Update function settings
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (UpdateFunctionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Function
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionRequest,
+
+) -> Response[Error | Function]:
+ """ Update function settings
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (UpdateFunctionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Function]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionRequest,
+
+) -> Error | Function | None:
+ """ Update function settings
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ body (UpdateFunctionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Function
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/functions/update_function_scheduler.py b/src/volcano_sdk/_generated/api/functions/update_function_scheduler.py
new file mode 100644
index 00000000..1c52aa9f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/functions/update_function_scheduler.py
@@ -0,0 +1,218 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.function_scheduler import FunctionScheduler
+from ...models.update_function_scheduler_request import UpdateFunctionSchedulerRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ body: UpdateFunctionSchedulerRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/projects/{id}/functions/{function_id}/schedulers/{scheduler_id}".format(id=quote(str(id), safe=""),function_id=quote(str(function_id), safe=""),scheduler_id=quote(str(scheduler_id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> FunctionScheduler | None:
+ if response.status_code == 200:
+ response_200 = FunctionScheduler.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[FunctionScheduler]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionSchedulerRequest,
+
+) -> Response[FunctionScheduler]:
+ """ Update a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+ body (UpdateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionScheduler]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionSchedulerRequest,
+
+) -> FunctionScheduler | None:
+ """ Update a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+ body (UpdateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionScheduler
+ """
+
+
+ return sync_detailed(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionSchedulerRequest,
+
+) -> Response[FunctionScheduler]:
+ """ Update a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+ body (UpdateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[FunctionScheduler]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ function_id: UUID,
+ scheduler_id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateFunctionSchedulerRequest,
+
+) -> FunctionScheduler | None:
+ """ Update a function scheduler
+
+ Args:
+ id (UUID):
+ function_id (UUID):
+ scheduler_id (UUID):
+ body (UpdateFunctionSchedulerRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ FunctionScheduler
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+function_id=function_id,
+scheduler_id=scheduler_id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/git_connections/__init__.py b/src/volcano_sdk/_generated/api/git_connections/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/git_connections/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/git_connections/delete_git_connection.py b/src/volcano_sdk/_generated/api/git_connections/delete_git_connection.py
new file mode 100644
index 00000000..623533cf
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/git_connections/delete_git_connection.py
@@ -0,0 +1,204 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ connection_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/user/git/connections/{connection_id}".format(connection_id=quote(str(connection_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a git provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a git provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ connection_id=connection_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a git provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a git provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ connection_id=connection_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/git_connections/git_connect_callback.py b/src/volcano_sdk/_generated/api/git_connections/git_connect_callback.py
new file mode 100644
index 00000000..0906935c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/git_connections/git_connect_callback.py
@@ -0,0 +1,247 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ code: str | Unset = UNSET,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["code"] = code
+
+ params["state"] = state
+
+ params["error"] = error
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/github/callback",
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 303:
+ response_303 = cast(Any, None)
+ return response_303
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+ code: str | Unset = UNSET,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Response[Any | Error]:
+ """ Complete a GitHub App connection callback
+
+ Public GitHub App callback. The signed state and callback binding cookie
+ bind the provider authorization to the browser that started the flow.
+
+ Args:
+ code (str | Unset):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ code=code,
+state=state,
+error=error,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+ code: str | Unset = UNSET,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Any | Error | None:
+ """ Complete a GitHub App connection callback
+
+ Public GitHub App callback. The signed state and callback binding cookie
+ bind the provider authorization to the browser that started the flow.
+
+ Args:
+ code (str | Unset):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+code=code,
+state=state,
+error=error,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+ code: str | Unset = UNSET,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Response[Any | Error]:
+ """ Complete a GitHub App connection callback
+
+ Public GitHub App callback. The signed state and callback binding cookie
+ bind the provider authorization to the browser that started the flow.
+
+ Args:
+ code (str | Unset):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ code=code,
+state=state,
+error=error,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+ code: str | Unset = UNSET,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Any | Error | None:
+ """ Complete a GitHub App connection callback
+
+ Public GitHub App callback. The signed state and callback binding cookie
+ bind the provider authorization to the browser that started the flow.
+
+ Args:
+ code (str | Unset):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+code=code,
+state=state,
+error=error,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/git_connections/list_git_connections.py b/src/volcano_sdk/_generated/api/git_connections/list_git_connections.py
new file mode 100644
index 00000000..f6804752
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/git_connections/list_git_connections.py
@@ -0,0 +1,172 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.git_connections_response import GitConnectionsResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/user/git/connections",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | GitConnectionsResponse | None:
+ if response.status_code == 200:
+ response_200 = GitConnectionsResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | GitConnectionsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GitConnectionsResponse]:
+ """ List git provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitConnectionsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GitConnectionsResponse | None:
+ """ List git provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitConnectionsResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GitConnectionsResponse]:
+ """ List git provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitConnectionsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GitConnectionsResponse | None:
+ """ List git provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitConnectionsResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/git_connections/list_git_installation_repositories.py b/src/volcano_sdk/_generated/api/git_connections/list_git_installation_repositories.py
new file mode 100644
index 00000000..01a19800
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/git_connections/list_git_installation_repositories.py
@@ -0,0 +1,237 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.git_repositories_response import GitRepositoriesResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ connection_id: UUID,
+ installation_id: int,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/user/git/connections/{connection_id}/installations/{installation_id}/repositories".format(connection_id=quote(str(connection_id), safe=""),installation_id=quote(str(installation_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | GitRepositoriesResponse | None:
+ if response.status_code == 200:
+ response_200 = GitRepositoriesResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | GitRepositoriesResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ connection_id: UUID,
+ installation_id: int,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GitRepositoriesResponse]:
+ """ List repos accessible to a connection through an installation
+
+ Live proxy to GitHub: lists the repos the connection's stored user
+ token can access through installationId. Nothing is persisted by this
+ call.
+
+ Args:
+ connection_id (UUID):
+ installation_id (int):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitRepositoriesResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+installation_id=installation_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ connection_id: UUID,
+ installation_id: int,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GitRepositoriesResponse | None:
+ """ List repos accessible to a connection through an installation
+
+ Live proxy to GitHub: lists the repos the connection's stored user
+ token can access through installationId. Nothing is persisted by this
+ call.
+
+ Args:
+ connection_id (UUID):
+ installation_id (int):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitRepositoriesResponse
+ """
+
+
+ return sync_detailed(
+ connection_id=connection_id,
+installation_id=installation_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ connection_id: UUID,
+ installation_id: int,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GitRepositoriesResponse]:
+ """ List repos accessible to a connection through an installation
+
+ Live proxy to GitHub: lists the repos the connection's stored user
+ token can access through installationId. Nothing is persisted by this
+ call.
+
+ Args:
+ connection_id (UUID):
+ installation_id (int):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitRepositoriesResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+installation_id=installation_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ connection_id: UUID,
+ installation_id: int,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GitRepositoriesResponse | None:
+ """ List repos accessible to a connection through an installation
+
+ Live proxy to GitHub: lists the repos the connection's stored user
+ token can access through installationId. Nothing is persisted by this
+ call.
+
+ Args:
+ connection_id (UUID):
+ installation_id (int):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitRepositoriesResponse
+ """
+
+
+ return (await asyncio_detailed(
+ connection_id=connection_id,
+installation_id=installation_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/git_connections/list_git_installations.py b/src/volcano_sdk/_generated/api/git_connections/list_git_installations.py
new file mode 100644
index 00000000..0569b668
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/git_connections/list_git_installations.py
@@ -0,0 +1,224 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.git_installations_response import GitInstallationsResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ connection_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/user/git/connections/{connection_id}/installations".format(connection_id=quote(str(connection_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | GitInstallationsResponse | None:
+ if response.status_code == 200:
+ response_200 = GitInstallationsResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | GitInstallationsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GitInstallationsResponse]:
+ """ List GitHub App installations accessible to a connection
+
+ Live proxy to GitHub: lists the platform GitHub App installations the
+ connection's stored user token can access. Nothing is persisted by
+ this call.
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitInstallationsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GitInstallationsResponse | None:
+ """ List GitHub App installations accessible to a connection
+
+ Live proxy to GitHub: lists the platform GitHub App installations the
+ connection's stored user token can access. Nothing is persisted by
+ this call.
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitInstallationsResponse
+ """
+
+
+ return sync_detailed(
+ connection_id=connection_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GitInstallationsResponse]:
+ """ List GitHub App installations accessible to a connection
+
+ Live proxy to GitHub: lists the platform GitHub App installations the
+ connection's stored user token can access. Nothing is persisted by
+ this call.
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitInstallationsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GitInstallationsResponse | None:
+ """ List GitHub App installations accessible to a connection
+
+ Live proxy to GitHub: lists the platform GitHub App installations the
+ connection's stored user token can access. Nothing is persisted by
+ this call.
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitInstallationsResponse
+ """
+
+
+ return (await asyncio_detailed(
+ connection_id=connection_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/git_connections/start_git_connect.py b/src/volcano_sdk/_generated/api/git_connections/start_git_connect.py
new file mode 100644
index 00000000..7fe021b1
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/git_connections/start_git_connect.py
@@ -0,0 +1,250 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.git_connect_start_response import GitConnectStartResponse
+from ...models.start_git_connect_provider import check_start_git_connect_provider
+from ...models.start_git_connect_provider import StartGitConnectProvider
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ provider: StartGitConnectProvider | Unset = 'github',
+ redirect: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_provider: str | Unset = UNSET
+ if not isinstance(provider, Unset):
+ json_provider = provider
+
+ params["provider"] = json_provider
+
+ params["redirect"] = redirect
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/user/git/connect",
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | GitConnectStartResponse | None:
+ if response.status_code == 200:
+ response_200 = GitConnectStartResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | GitConnectStartResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ provider: StartGitConnectProvider | Unset = 'github',
+ redirect: str | Unset = UNSET,
+
+) -> Response[Error | GitConnectStartResponse]:
+ """ Start a git provider connection
+
+ Starts a first-party dashboard user's git provider connection flow and
+ returns the provider authorization URL. The response also sets a
+ short-lived HttpOnly callback binding cookie tied to the authenticated
+ user through the signed provider state.
+
+ Args:
+ provider (StartGitConnectProvider | Unset): Default: 'github'.
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitConnectStartResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+redirect=redirect,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ provider: StartGitConnectProvider | Unset = 'github',
+ redirect: str | Unset = UNSET,
+
+) -> Error | GitConnectStartResponse | None:
+ """ Start a git provider connection
+
+ Starts a first-party dashboard user's git provider connection flow and
+ returns the provider authorization URL. The response also sets a
+ short-lived HttpOnly callback binding cookie tied to the authenticated
+ user through the signed provider state.
+
+ Args:
+ provider (StartGitConnectProvider | Unset): Default: 'github'.
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitConnectStartResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+provider=provider,
+redirect=redirect,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ provider: StartGitConnectProvider | Unset = 'github',
+ redirect: str | Unset = UNSET,
+
+) -> Response[Error | GitConnectStartResponse]:
+ """ Start a git provider connection
+
+ Starts a first-party dashboard user's git provider connection flow and
+ returns the provider authorization URL. The response also sets a
+ short-lived HttpOnly callback binding cookie tied to the authenticated
+ user through the signed provider state.
+
+ Args:
+ provider (StartGitConnectProvider | Unset): Default: 'github'.
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GitConnectStartResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+redirect=redirect,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ provider: StartGitConnectProvider | Unset = 'github',
+ redirect: str | Unset = UNSET,
+
+) -> Error | GitConnectStartResponse | None:
+ """ Start a git provider connection
+
+ Starts a first-party dashboard user's git provider connection flow and
+ returns the provider authorization URL. The response also sets a
+ short-lived HttpOnly callback binding cookie tied to the authenticated
+ user through the signed provider state.
+
+ Args:
+ provider (StartGitConnectProvider | Unset): Default: 'github'.
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GitConnectStartResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+provider=provider,
+redirect=redirect,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/locks/__init__.py b/src/volcano_sdk/_generated/api/locks/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/locks/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/locks/acquire_project_lock.py b/src/volcano_sdk/_generated/api/locks/acquire_project_lock.py
new file mode 100644
index 00000000..8f8ee971
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/locks/acquire_project_lock.py
@@ -0,0 +1,289 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_lock_lease import ProjectLockLease
+from ...models.project_lock_lease_request import ProjectLockLeaseRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ key: str,
+ *,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["X-Volcano-Lock-Token"] = x_volcano_lock_token
+
+ headers["X-Volcano-Request-Id"] = x_volcano_request_id
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/locks/{key}/lease".format(key=quote(str(key), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectLockLease | None:
+ if response.status_code == 201:
+ response_201 = ProjectLockLease.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectLockLease]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Response[Error | ProjectLockLease]:
+ """ Acquire a project lock
+
+ Acquires a project-scoped lease using the project embedded in the service-role key.
+ The caller must hold the `locks.manage` permission. Repeating the request with the
+ same lock token is idempotent and resets that lease to the requested TTL. A different
+ live owner receives `409 lock_held`; a caller whose own lease already lapsed receives
+ `409 lock_ownership_lost`.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectLockLease]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Error | ProjectLockLease | None:
+ """ Acquire a project lock
+
+ Acquires a project-scoped lease using the project embedded in the service-role key.
+ The caller must hold the `locks.manage` permission. Repeating the request with the
+ same lock token is idempotent and resets that lease to the requested TTL. A different
+ live owner receives `409 lock_held`; a caller whose own lease already lapsed receives
+ `409 lock_ownership_lost`.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectLockLease
+ """
+
+
+ return sync_detailed(
+ key=key,
+client=client,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Response[Error | ProjectLockLease]:
+ """ Acquire a project lock
+
+ Acquires a project-scoped lease using the project embedded in the service-role key.
+ The caller must hold the `locks.manage` permission. Repeating the request with the
+ same lock token is idempotent and resets that lease to the requested TTL. A different
+ live owner receives `409 lock_held`; a caller whose own lease already lapsed receives
+ `409 lock_ownership_lost`.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectLockLease]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Error | ProjectLockLease | None:
+ """ Acquire a project lock
+
+ Acquires a project-scoped lease using the project embedded in the service-role key.
+ The caller must hold the `locks.manage` permission. Repeating the request with the
+ same lock token is idempotent and resets that lease to the requested TTL. A different
+ live owner receives `409 lock_held`; a caller whose own lease already lapsed receives
+ `409 lock_ownership_lost`.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectLockLease
+ """
+
+
+ return (await asyncio_detailed(
+ key=key,
+client=client,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/locks/force_release_project_lock.py b/src/volcano_sdk/_generated/api/locks/force_release_project_lock.py
new file mode 100644
index 00000000..82428268
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/locks/force_release_project_lock.py
@@ -0,0 +1,254 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ key: str,
+ *,
+ x_volcano_request_id: UUID,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["X-Volcano-Request-Id"] = x_volcano_request_id
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/locks/{key}".format(key=quote(str(key), safe=""),),
+ }
+
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Response[Any | Error]:
+ """ Force release a project lock
+
+ Drops the lease whatever token holds it, for recovering a lock whose holder
+ died without releasing. Use `DELETE /locks/{key}/lease` for normal release.
+
+ This breaks mutual exclusion by itself: the previous holder keeps working
+ until its own renewal fails. Guard the protected resource with the lease's
+ `fencing_token`, which the next acquisition raises, so a write from the
+ displaced holder can be rejected. Succeeds when the lock is already absent.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Any | Error | None:
+ """ Force release a project lock
+
+ Drops the lease whatever token holds it, for recovering a lock whose holder
+ died without releasing. Use `DELETE /locks/{key}/lease` for normal release.
+
+ This breaks mutual exclusion by itself: the previous holder keeps working
+ until its own renewal fails. Guard the protected resource with the lease's
+ `fencing_token`, which the next acquisition raises, so a write from the
+ displaced holder can be rejected. Succeeds when the lock is already absent.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ key=key,
+client=client,
+x_volcano_request_id=x_volcano_request_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Response[Any | Error]:
+ """ Force release a project lock
+
+ Drops the lease whatever token holds it, for recovering a lock whose holder
+ died without releasing. Use `DELETE /locks/{key}/lease` for normal release.
+
+ This breaks mutual exclusion by itself: the previous holder keeps working
+ until its own renewal fails. Guard the protected resource with the lease's
+ `fencing_token`, which the next acquisition raises, so a write from the
+ displaced holder can be rejected. Succeeds when the lock is already absent.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Any | Error | None:
+ """ Force release a project lock
+
+ Drops the lease whatever token holds it, for recovering a lock whose holder
+ died without releasing. Use `DELETE /locks/{key}/lease` for normal release.
+
+ This breaks mutual exclusion by itself: the previous holder keeps working
+ until its own renewal fails. Guard the protected resource with the lease's
+ `fencing_token`, which the next acquisition raises, so a write from the
+ displaced holder can be rejected. Succeeds when the lock is already absent.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ key=key,
+client=client,
+x_volcano_request_id=x_volcano_request_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/locks/get_project_lock.py b/src/volcano_sdk/_generated/api/locks/get_project_lock.py
new file mode 100644
index 00000000..3ec6f530
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/locks/get_project_lock.py
@@ -0,0 +1,246 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_lock_state import ProjectLockState
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ key: str,
+ *,
+ x_volcano_request_id: UUID,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["X-Volcano-Request-Id"] = x_volcano_request_id
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/locks/{key}".format(key=quote(str(key), safe=""),),
+ }
+
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectLockState | None:
+ if response.status_code == 200:
+ response_200 = ProjectLockState.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectLockState]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Response[Error | ProjectLockState]:
+ """ Read a project lock
+
+ Reports whether the lock is currently held, when its lease expires, and the
+ holder's fencing token. `held` follows takeover eligibility rather than raw
+ expiry, so `held: false` means an acquire would succeed now. No lock token is
+ required, making this usable for monitoring and recovery.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectLockState]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Error | ProjectLockState | None:
+ """ Read a project lock
+
+ Reports whether the lock is currently held, when its lease expires, and the
+ holder's fencing token. `held` follows takeover eligibility rather than raw
+ expiry, so `held: false` means an acquire would succeed now. No lock token is
+ required, making this usable for monitoring and recovery.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectLockState
+ """
+
+
+ return sync_detailed(
+ key=key,
+client=client,
+x_volcano_request_id=x_volcano_request_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Response[Error | ProjectLockState]:
+ """ Read a project lock
+
+ Reports whether the lock is currently held, when its lease expires, and the
+ holder's fencing token. `held` follows takeover eligibility rather than raw
+ expiry, so `held: false` means an acquire would succeed now. No lock token is
+ required, making this usable for monitoring and recovery.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectLockState]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_request_id: UUID,
+
+) -> Error | ProjectLockState | None:
+ """ Read a project lock
+
+ Reports whether the lock is currently held, when its lease expires, and the
+ holder's fencing token. `held` follows takeover eligibility rather than raw
+ expiry, so `held: false` means an acquire would succeed now. No lock token is
+ required, making this usable for monitoring and recovery.
+
+ Args:
+ key (str):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectLockState
+ """
+
+
+ return (await asyncio_detailed(
+ key=key,
+client=client,
+x_volcano_request_id=x_volcano_request_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/locks/release_project_lock.py b/src/volcano_sdk/_generated/api/locks/release_project_lock.py
new file mode 100644
index 00000000..c6b782f3
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/locks/release_project_lock.py
@@ -0,0 +1,252 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ key: str,
+ *,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["X-Volcano-Lock-Token"] = x_volcano_lock_token
+
+ headers["X-Volcano-Request-Id"] = x_volcano_request_id
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/locks/{key}/lease".format(key=quote(str(key), safe=""),),
+ }
+
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Response[Any | Error]:
+ """ Release a project lock
+
+ Releases a lease only when the supplied lock token still owns it.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Any | Error | None:
+ """ Release a project lock
+
+ Releases a lease only when the supplied lock token still owns it.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ key=key,
+client=client,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Response[Any | Error]:
+ """ Release a project lock
+
+ Releases a lease only when the supplied lock token still owns it.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Any | Error | None:
+ """ Release a project lock
+
+ Releases a lease only when the supplied lock token still owns it.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ key=key,
+client=client,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/locks/renew_project_lock.py b/src/volcano_sdk/_generated/api/locks/renew_project_lock.py
new file mode 100644
index 00000000..b1705e08
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/locks/renew_project_lock.py
@@ -0,0 +1,285 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_lock_lease import ProjectLockLease
+from ...models.project_lock_lease_request import ProjectLockLeaseRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ key: str,
+ *,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["X-Volcano-Lock-Token"] = x_volcano_lock_token
+
+ headers["X-Volcano-Request-Id"] = x_volcano_request_id
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/locks/{key}/lease".format(key=quote(str(key), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectLockLease | None:
+ if response.status_code == 200:
+ response_200 = ProjectLockLease.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectLockLease]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Response[Error | ProjectLockLease]:
+ """ Renew a project lock
+
+ Renews a lease owned by the supplied lock token. The request must arrive
+ more than one second before `expires_at`; this safety margin prevents
+ clock skew between regional API instances from resurrecting an expired
+ lease.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectLockLease]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Error | ProjectLockLease | None:
+ """ Renew a project lock
+
+ Renews a lease owned by the supplied lock token. The request must arrive
+ more than one second before `expires_at`; this safety margin prevents
+ clock skew between regional API instances from resurrecting an expired
+ lease.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectLockLease
+ """
+
+
+ return sync_detailed(
+ key=key,
+client=client,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Response[Error | ProjectLockLease]:
+ """ Renew a project lock
+
+ Renews a lease owned by the supplied lock token. The request must arrive
+ more than one second before `expires_at`; this safety margin prevents
+ clock skew between regional API instances from resurrecting an expired
+ lease.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectLockLease]
+ """
+
+
+ kwargs = _get_kwargs(
+ key=key,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ key: str,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectLockLeaseRequest,
+ x_volcano_lock_token: UUID,
+ x_volcano_request_id: UUID,
+
+) -> Error | ProjectLockLease | None:
+ """ Renew a project lock
+
+ Renews a lease owned by the supplied lock token. The request must arrive
+ more than one second before `expires_at`; this safety margin prevents
+ clock skew between regional API instances from resurrecting an expired
+ lease.
+
+ Args:
+ key (str):
+ x_volcano_lock_token (UUID):
+ x_volcano_request_id (UUID):
+ body (ProjectLockLeaseRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectLockLease
+ """
+
+
+ return (await asyncio_detailed(
+ key=key,
+client=client,
+body=body,
+x_volcano_lock_token=x_volcano_lock_token,
+x_volcano_request_id=x_volcano_request_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/logs/__init__.py b/src/volcano_sdk/_generated/api/logs/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/logs/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/logs/get_project_log_activity.py b/src/volcano_sdk/_generated/api/logs/get_project_log_activity.py
new file mode 100644
index 00000000..4cf36fcc
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/logs/get_project_log_activity.py
@@ -0,0 +1,261 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.log_activity_request import LogActivityRequest
+from ...models.log_activity_response import LogActivityResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: LogActivityRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/logs/activity".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | LogActivityResponse | None:
+ if response.status_code == 200:
+ response_200 = LogActivityResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | LogActivityResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogActivityRequest,
+
+) -> Response[Error | LogActivityResponse]:
+ """ Get project log activity
+
+ Retrieve bucketed log counts for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to count deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The activity window is limited
+ to the plan's retention window (FREE: 1 day, PRO: 30 days); older start
+ times are clamped to that window.
+
+ Args:
+ id (UUID):
+ body (LogActivityRequest): Activity request for bucketed log counts.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | LogActivityResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogActivityRequest,
+
+) -> Error | LogActivityResponse | None:
+ """ Get project log activity
+
+ Retrieve bucketed log counts for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to count deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The activity window is limited
+ to the plan's retention window (FREE: 1 day, PRO: 30 days); older start
+ times are clamped to that window.
+
+ Args:
+ id (UUID):
+ body (LogActivityRequest): Activity request for bucketed log counts.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | LogActivityResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogActivityRequest,
+
+) -> Response[Error | LogActivityResponse]:
+ """ Get project log activity
+
+ Retrieve bucketed log counts for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to count deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The activity window is limited
+ to the plan's retention window (FREE: 1 day, PRO: 30 days); older start
+ times are clamped to that window.
+
+ Args:
+ id (UUID):
+ body (LogActivityRequest): Activity request for bucketed log counts.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | LogActivityResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogActivityRequest,
+
+) -> Error | LogActivityResponse | None:
+ """ Get project log activity
+
+ Retrieve bucketed log counts for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to count deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The activity window is limited
+ to the plan's retention window (FREE: 1 day, PRO: 30 days); older start
+ times are clamped to that window.
+
+ Args:
+ id (UUID):
+ body (LogActivityRequest): Activity request for bucketed log counts.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | LogActivityResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/logs/search_project_logs.py b/src/volcano_sdk/_generated/api/logs/search_project_logs.py
new file mode 100644
index 00000000..64a34a33
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/logs/search_project_logs.py
@@ -0,0 +1,265 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.log_search_request import LogSearchRequest
+from ...models.log_search_response import LogSearchResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: LogSearchRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/logs/search".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | LogSearchResponse | None:
+ if response.status_code == 200:
+ response_200 = LogSearchResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | LogSearchResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogSearchRequest,
+
+) -> Response[Error | LogSearchResponse]:
+ """ Search project logs
+
+ Search or filter logs for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to read deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; requests for
+ `resource.type=database` from a FREE-plan project owner return 403.
+ Log history (runtime and deployment) is limited to the plan's retention
+ window (FREE: 1 day, PRO: 30 days); older time ranges are clamped to that
+ window.
+
+ Args:
+ id (UUID):
+ body (LogSearchRequest): Search request for project logs.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | LogSearchResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogSearchRequest,
+
+) -> Error | LogSearchResponse | None:
+ """ Search project logs
+
+ Search or filter logs for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to read deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; requests for
+ `resource.type=database` from a FREE-plan project owner return 403.
+ Log history (runtime and deployment) is limited to the plan's retention
+ window (FREE: 1 day, PRO: 30 days); older time ranges are clamped to that
+ window.
+
+ Args:
+ id (UUID):
+ body (LogSearchRequest): Search request for project logs.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | LogSearchResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogSearchRequest,
+
+) -> Response[Error | LogSearchResponse]:
+ """ Search project logs
+
+ Search or filter logs for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to read deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; requests for
+ `resource.type=database` from a FREE-plan project owner return 403.
+ Log history (runtime and deployment) is limited to the plan's retention
+ window (FREE: 1 day, PRO: 30 days); older time ranges are clamped to that
+ window.
+
+ Args:
+ id (UUID):
+ body (LogSearchRequest): Search request for project logs.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | LogSearchResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogSearchRequest,
+
+) -> Error | LogSearchResponse | None:
+ """ Search project logs
+
+ Search or filter logs for one resource type in the project. Set
+ `resource.type` to `function`, `frontend`, or `database`. Add
+ `resource.ids` to filter to one or more resources, and add
+ `resource.deployments.ids` to read deployment logs instead of runtime
+ logs for functions and frontends. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; requests for
+ `resource.type=database` from a FREE-plan project owner return 403.
+ Log history (runtime and deployment) is limited to the plan's retention
+ window (FREE: 1 day, PRO: 30 days); older time ranges are clamped to that
+ window.
+
+ Args:
+ id (UUID):
+ body (LogSearchRequest): Search request for project logs.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | LogSearchResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/logs/stream_project_logs.py b/src/volcano_sdk/_generated/api/logs/stream_project_logs.py
new file mode 100644
index 00000000..7ff83351
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/logs/stream_project_logs.py
@@ -0,0 +1,345 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.log_stream_request import LogStreamRequest
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: LogStreamRequest,
+ last_event_id_query: str | Unset = UNSET,
+ last_event_id_header: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ if not isinstance(last_event_id_header, Unset):
+ headers["Last-Event-ID"] = last_event_id_header
+
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["last_event_id"] = last_event_id_query
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/logs/stream".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | str | None:
+ if response.status_code == 200:
+ response_200 = response.text
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | str]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogStreamRequest,
+ last_event_id_query: str | Unset = UNSET,
+ last_event_id_header: str | Unset = UNSET,
+
+) -> Response[Error | str]:
+ """ Stream project logs
+
+ Live-tail project logs as Server-Sent Events. The request body uses the
+ resource selector plus `q`, `start_time`, and `limit`,
+ including runtime logs and function/frontend deployment logs selected
+ with `resource.deployments`. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The `q` field uses the same
+ syntax as search and activity requests. Do not send `cursor` or
+ `end_time`; use `/logs/search` for range backfills.
+ Explicit historical `start_time` values are limited to the plan's
+ retention window (FREE: 1 day, PRO: 30 days). Resume with
+ `Last-Event-ID` or the `last_event_id` query parameter. The cursor is
+ bound to the request body: the resource selector and every filter must
+ match the original request when reconnecting, otherwise the request is
+ rejected with `400`.
+
+ This is a live tail, not a gap-free backfill. On connect or reconnect the
+ server delivers at most `limit` of the most recent matching events from
+ the cursor position and then follows new events; events older than that
+ window are not replayed. Use `/logs/search` to backfill a time range.
+
+ Args:
+ id (UUID):
+ last_event_id_query (str | Unset):
+ last_event_id_header (str | Unset):
+ body (LogStreamRequest): Stream request for live project logs. Pagination cursors and
+ fixed end times are not supported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | str]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+last_event_id_query=last_event_id_query,
+last_event_id_header=last_event_id_header,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogStreamRequest,
+ last_event_id_query: str | Unset = UNSET,
+ last_event_id_header: str | Unset = UNSET,
+
+) -> Error | str | None:
+ """ Stream project logs
+
+ Live-tail project logs as Server-Sent Events. The request body uses the
+ resource selector plus `q`, `start_time`, and `limit`,
+ including runtime logs and function/frontend deployment logs selected
+ with `resource.deployments`. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The `q` field uses the same
+ syntax as search and activity requests. Do not send `cursor` or
+ `end_time`; use `/logs/search` for range backfills.
+ Explicit historical `start_time` values are limited to the plan's
+ retention window (FREE: 1 day, PRO: 30 days). Resume with
+ `Last-Event-ID` or the `last_event_id` query parameter. The cursor is
+ bound to the request body: the resource selector and every filter must
+ match the original request when reconnecting, otherwise the request is
+ rejected with `400`.
+
+ This is a live tail, not a gap-free backfill. On connect or reconnect the
+ server delivers at most `limit` of the most recent matching events from
+ the cursor position and then follows new events; events older than that
+ window are not replayed. Use `/logs/search` to backfill a time range.
+
+ Args:
+ id (UUID):
+ last_event_id_query (str | Unset):
+ last_event_id_header (str | Unset):
+ body (LogStreamRequest): Stream request for live project logs. Pagination cursors and
+ fixed end times are not supported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | str
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+last_event_id_query=last_event_id_query,
+last_event_id_header=last_event_id_header,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogStreamRequest,
+ last_event_id_query: str | Unset = UNSET,
+ last_event_id_header: str | Unset = UNSET,
+
+) -> Response[Error | str]:
+ """ Stream project logs
+
+ Live-tail project logs as Server-Sent Events. The request body uses the
+ resource selector plus `q`, `start_time`, and `limit`,
+ including runtime logs and function/frontend deployment logs selected
+ with `resource.deployments`. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The `q` field uses the same
+ syntax as search and activity requests. Do not send `cursor` or
+ `end_time`; use `/logs/search` for range backfills.
+ Explicit historical `start_time` values are limited to the plan's
+ retention window (FREE: 1 day, PRO: 30 days). Resume with
+ `Last-Event-ID` or the `last_event_id` query parameter. The cursor is
+ bound to the request body: the resource selector and every filter must
+ match the original request when reconnecting, otherwise the request is
+ rejected with `400`.
+
+ This is a live tail, not a gap-free backfill. On connect or reconnect the
+ server delivers at most `limit` of the most recent matching events from
+ the cursor position and then follows new events; events older than that
+ window are not replayed. Use `/logs/search` to backfill a time range.
+
+ Args:
+ id (UUID):
+ last_event_id_query (str | Unset):
+ last_event_id_header (str | Unset):
+ body (LogStreamRequest): Stream request for live project logs. Pagination cursors and
+ fixed end times are not supported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | str]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+last_event_id_query=last_event_id_query,
+last_event_id_header=last_event_id_header,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: LogStreamRequest,
+ last_event_id_query: str | Unset = UNSET,
+ last_event_id_header: str | Unset = UNSET,
+
+) -> Error | str | None:
+ """ Stream project logs
+
+ Live-tail project logs as Server-Sent Events. The request body uses the
+ resource selector plus `q`, `start_time`, and `limit`,
+ including runtime logs and function/frontend deployment logs selected
+ with `resource.deployments`. Deployment logs are not supported for
+ databases. Database logs are a PRO-plan feature; `resource.type=database`
+ from a FREE-plan project owner returns 403. The `q` field uses the same
+ syntax as search and activity requests. Do not send `cursor` or
+ `end_time`; use `/logs/search` for range backfills.
+ Explicit historical `start_time` values are limited to the plan's
+ retention window (FREE: 1 day, PRO: 30 days). Resume with
+ `Last-Event-ID` or the `last_event_id` query parameter. The cursor is
+ bound to the request body: the resource selector and every filter must
+ match the original request when reconnecting, otherwise the request is
+ rejected with `400`.
+
+ This is a live tail, not a gap-free backfill. On connect or reconnect the
+ server delivers at most `limit` of the most recent matching events from
+ the cursor position and then follows new events; events older than that
+ window are not replayed. Use `/logs/search` to backfill a time range.
+
+ Args:
+ id (UUID):
+ last_event_id_query (str | Unset):
+ last_event_id_header (str | Unset):
+ body (LogStreamRequest): Stream request for live project logs. Pagination cursors and
+ fixed end times are not supported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | str
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+last_event_id_query=last_event_id_query,
+last_event_id_header=last_event_id_header,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/__init__.py b/src/volcano_sdk/_generated/api/o_auth_authentication/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_authorize.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_authorize.py
new file mode 100644
index 00000000..26f838dc
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_authorize.py
@@ -0,0 +1,266 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_device_authorize_body import AuthDeviceAuthorizeBody
+from ...models.device_authorization_response import DeviceAuthorizationResponse
+from ...models.o_auth_error_response import OAuthErrorResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthDeviceAuthorizeBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/device/authorize",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> DeviceAuthorizationResponse | OAuthErrorResponse | None:
+ if response.status_code == 200:
+ response_200 = DeviceAuthorizationResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = OAuthErrorResponse.from_dict(response.json())
+
+
+
+ return response_400
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[DeviceAuthorizationResponse | OAuthErrorResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceAuthorizeBody,
+
+) -> Response[DeviceAuthorizationResponse | OAuthErrorResponse]:
+ """ Start RFC8628 device authorization
+
+ Starts OAuth 2.0 Device Authorization Grant (RFC 8628).
+ Returns `device_code` for the CLI and `user_code` for browser verification.
+
+ By default the returned `verification_uri` / `verification_uri_complete`
+ point at the project's managed device-approval page served by this API
+ (`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`),
+ which requires managed auth enabled and a default anon key for the
+ project.
+
+ Projects can override this by setting `device_verification_url` on the
+ auth config (`PATCH /auth/config`). When set, that URL is returned as-is
+ with the `user_code` appended (no `action=device` hint and no embedded
+ anon key — the page brings its own), so a CLI's `login` command surfaces
+ the project's own RFC 8628 approval page. With a custom URL, device login
+ does **not** require managed auth to be enabled; the custom page's origin
+ must be in the project's auth CORS allowlist to call
+ `POST /auth/device/verify`. Either way the verification page must
+ authenticate the end user and call `POST /auth/device/verify` with the
+ `user_code`. See the device-auth guide for both approaches.
+
+ Args:
+ body (AuthDeviceAuthorizeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DeviceAuthorizationResponse | OAuthErrorResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceAuthorizeBody,
+
+) -> DeviceAuthorizationResponse | OAuthErrorResponse | None:
+ """ Start RFC8628 device authorization
+
+ Starts OAuth 2.0 Device Authorization Grant (RFC 8628).
+ Returns `device_code` for the CLI and `user_code` for browser verification.
+
+ By default the returned `verification_uri` / `verification_uri_complete`
+ point at the project's managed device-approval page served by this API
+ (`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`),
+ which requires managed auth enabled and a default anon key for the
+ project.
+
+ Projects can override this by setting `device_verification_url` on the
+ auth config (`PATCH /auth/config`). When set, that URL is returned as-is
+ with the `user_code` appended (no `action=device` hint and no embedded
+ anon key — the page brings its own), so a CLI's `login` command surfaces
+ the project's own RFC 8628 approval page. With a custom URL, device login
+ does **not** require managed auth to be enabled; the custom page's origin
+ must be in the project's auth CORS allowlist to call
+ `POST /auth/device/verify`. Either way the verification page must
+ authenticate the end user and call `POST /auth/device/verify` with the
+ `user_code`. See the device-auth guide for both approaches.
+
+ Args:
+ body (AuthDeviceAuthorizeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DeviceAuthorizationResponse | OAuthErrorResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceAuthorizeBody,
+
+) -> Response[DeviceAuthorizationResponse | OAuthErrorResponse]:
+ """ Start RFC8628 device authorization
+
+ Starts OAuth 2.0 Device Authorization Grant (RFC 8628).
+ Returns `device_code` for the CLI and `user_code` for browser verification.
+
+ By default the returned `verification_uri` / `verification_uri_complete`
+ point at the project's managed device-approval page served by this API
+ (`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`),
+ which requires managed auth enabled and a default anon key for the
+ project.
+
+ Projects can override this by setting `device_verification_url` on the
+ auth config (`PATCH /auth/config`). When set, that URL is returned as-is
+ with the `user_code` appended (no `action=device` hint and no embedded
+ anon key — the page brings its own), so a CLI's `login` command surfaces
+ the project's own RFC 8628 approval page. With a custom URL, device login
+ does **not** require managed auth to be enabled; the custom page's origin
+ must be in the project's auth CORS allowlist to call
+ `POST /auth/device/verify`. Either way the verification page must
+ authenticate the end user and call `POST /auth/device/verify` with the
+ `user_code`. See the device-auth guide for both approaches.
+
+ Args:
+ body (AuthDeviceAuthorizeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[DeviceAuthorizationResponse | OAuthErrorResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceAuthorizeBody,
+
+) -> DeviceAuthorizationResponse | OAuthErrorResponse | None:
+ """ Start RFC8628 device authorization
+
+ Starts OAuth 2.0 Device Authorization Grant (RFC 8628).
+ Returns `device_code` for the CLI and `user_code` for browser verification.
+
+ By default the returned `verification_uri` / `verification_uri_complete`
+ point at the project's managed device-approval page served by this API
+ (`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`),
+ which requires managed auth enabled and a default anon key for the
+ project.
+
+ Projects can override this by setting `device_verification_url` on the
+ auth config (`PATCH /auth/config`). When set, that URL is returned as-is
+ with the `user_code` appended (no `action=device` hint and no embedded
+ anon key — the page brings its own), so a CLI's `login` command surfaces
+ the project's own RFC 8628 approval page. With a custom URL, device login
+ does **not** require managed auth to be enabled; the custom page's origin
+ must be in the project's auth CORS allowlist to call
+ `POST /auth/device/verify`. Either way the verification page must
+ authenticate the end user and call `POST /auth/device/verify` with the
+ `user_code`. See the device-auth guide for both approaches.
+
+ Args:
+ body (AuthDeviceAuthorizeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ DeviceAuthorizationResponse | OAuthErrorResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_token.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_token.py
new file mode 100644
index 00000000..c9ebdd7d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_token.py
@@ -0,0 +1,209 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_device_token_body import AuthDeviceTokenBody
+from ...models.auth_token_response import AuthTokenResponse
+from ...models.o_auth_error_response import OAuthErrorResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthDeviceTokenBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/device/token",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthTokenResponse | OAuthErrorResponse | None:
+ if response.status_code == 200:
+ response_200 = AuthTokenResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = OAuthErrorResponse.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = OAuthErrorResponse.from_dict(response.json())
+
+
+
+ return response_403
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthTokenResponse | OAuthErrorResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceTokenBody,
+
+) -> Response[AuthTokenResponse | OAuthErrorResponse]:
+ """ Poll device token endpoint
+
+ RFC8628 token polling endpoint.
+ Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and
+ `expired_token`.
+
+ Args:
+ body (AuthDeviceTokenBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthTokenResponse | OAuthErrorResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceTokenBody,
+
+) -> AuthTokenResponse | OAuthErrorResponse | None:
+ """ Poll device token endpoint
+
+ RFC8628 token polling endpoint.
+ Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and
+ `expired_token`.
+
+ Args:
+ body (AuthDeviceTokenBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthTokenResponse | OAuthErrorResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceTokenBody,
+
+) -> Response[AuthTokenResponse | OAuthErrorResponse]:
+ """ Poll device token endpoint
+
+ RFC8628 token polling endpoint.
+ Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and
+ `expired_token`.
+
+ Args:
+ body (AuthDeviceTokenBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthTokenResponse | OAuthErrorResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+ body: AuthDeviceTokenBody,
+
+) -> AuthTokenResponse | OAuthErrorResponse | None:
+ """ Poll device token endpoint
+
+ RFC8628 token polling endpoint.
+ Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and
+ `expired_token`.
+
+ Args:
+ body (AuthDeviceTokenBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthTokenResponse | OAuthErrorResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_verify.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_verify.py
new file mode 100644
index 00000000..ae9be0cb
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_device_verify.py
@@ -0,0 +1,230 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_device_verify_body import AuthDeviceVerifyBody
+from ...models.auth_device_verify_response_200 import AuthDeviceVerifyResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthDeviceVerifyBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/device/verify",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthDeviceVerifyResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthDeviceVerifyResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthDeviceVerifyResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthDeviceVerifyBody,
+
+) -> Response[AuthDeviceVerifyResponse200 | Error]:
+ """ Approve or deny a device code
+
+ Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a
+ `user_code`.
+
+ Called by the verification page after the end user signs in. The grant is
+ scoped to the project the auth-user token belongs to: approving a
+ `user_code` issued for a different project returns `403`. This endpoint
+ does not require managed auth to be enabled, so a custom verification page
+ (hosted anywhere) can drive approval — it just needs an authenticated
+ project auth-user access token and, for cross-origin browser calls, the
+ page origin allowed in the project's auth CORS settings.
+
+ Args:
+ body (AuthDeviceVerifyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthDeviceVerifyResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthDeviceVerifyBody,
+
+) -> AuthDeviceVerifyResponse200 | Error | None:
+ """ Approve or deny a device code
+
+ Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a
+ `user_code`.
+
+ Called by the verification page after the end user signs in. The grant is
+ scoped to the project the auth-user token belongs to: approving a
+ `user_code` issued for a different project returns `403`. This endpoint
+ does not require managed auth to be enabled, so a custom verification page
+ (hosted anywhere) can drive approval — it just needs an authenticated
+ project auth-user access token and, for cross-origin browser calls, the
+ page origin allowed in the project's auth CORS settings.
+
+ Args:
+ body (AuthDeviceVerifyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthDeviceVerifyResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthDeviceVerifyBody,
+
+) -> Response[AuthDeviceVerifyResponse200 | Error]:
+ """ Approve or deny a device code
+
+ Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a
+ `user_code`.
+
+ Called by the verification page after the end user signs in. The grant is
+ scoped to the project the auth-user token belongs to: approving a
+ `user_code` issued for a different project returns `403`. This endpoint
+ does not require managed auth to be enabled, so a custom verification page
+ (hosted anywhere) can drive approval — it just needs an authenticated
+ project auth-user access token and, for cross-origin browser calls, the
+ page origin allowed in the project's auth CORS settings.
+
+ Args:
+ body (AuthDeviceVerifyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthDeviceVerifyResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthDeviceVerifyBody,
+
+) -> AuthDeviceVerifyResponse200 | Error | None:
+ """ Approve or deny a device code
+
+ Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a
+ `user_code`.
+
+ Called by the verification page after the end user signs in. The grant is
+ scoped to the project the auth-user token belongs to: approving a
+ `user_code` issued for a different project returns `403`. This endpoint
+ does not require managed auth to be enabled, so a custom verification page
+ (hosted anywhere) can drive approval — it just needs an authenticated
+ project auth-user access token and, for cross-origin browser calls, the
+ page origin allowed in the project's auth CORS settings.
+
+ Args:
+ body (AuthDeviceVerifyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthDeviceVerifyResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_link_o_auth_provider.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_link_o_auth_provider.py
new file mode 100644
index 00000000..a16ef891
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_link_o_auth_provider.py
@@ -0,0 +1,272 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_link_o_auth_provider_provider import AuthLinkOAuthProviderProvider
+from ...models.auth_link_o_auth_provider_provider import check_auth_link_o_auth_provider_provider
+from ...models.auth_link_o_auth_provider_response_200 import AuthLinkOAuthProviderResponse200
+from ...models.auth_link_o_auth_provider_response_mode import AuthLinkOAuthProviderResponseMode
+from ...models.auth_link_o_auth_provider_response_mode import check_auth_link_o_auth_provider_response_mode
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: AuthLinkOAuthProviderProvider,
+ *,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthLinkOAuthProviderResponseMode | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["redirect_url"] = redirect_url
+
+ params["client_state"] = client_state
+
+ json_response_mode: str | Unset = UNSET
+ if not isinstance(response_mode, Unset):
+ json_response_mode = response_mode
+
+ params["response_mode"] = json_response_mode
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/oauth/{provider}/link".format(provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthLinkOAuthProviderResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthLinkOAuthProviderResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthLinkOAuthProviderResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: AuthLinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthLinkOAuthProviderResponseMode | Unset = UNSET,
+
+) -> Response[AuthLinkOAuthProviderResponse200 | Error]:
+ """ Link OAuth provider to current user
+
+ Generates authorization URL to link OAuth provider to existing account.
+ User must be authenticated.
+
+ Args:
+ provider (AuthLinkOAuthProviderProvider):
+ redirect_url (str | Unset):
+ client_state (str | Unset):
+ response_mode (AuthLinkOAuthProviderResponseMode | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthLinkOAuthProviderResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+redirect_url=redirect_url,
+client_state=client_state,
+response_mode=response_mode,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: AuthLinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthLinkOAuthProviderResponseMode | Unset = UNSET,
+
+) -> AuthLinkOAuthProviderResponse200 | Error | None:
+ """ Link OAuth provider to current user
+
+ Generates authorization URL to link OAuth provider to existing account.
+ User must be authenticated.
+
+ Args:
+ provider (AuthLinkOAuthProviderProvider):
+ redirect_url (str | Unset):
+ client_state (str | Unset):
+ response_mode (AuthLinkOAuthProviderResponseMode | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthLinkOAuthProviderResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+redirect_url=redirect_url,
+client_state=client_state,
+response_mode=response_mode,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: AuthLinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthLinkOAuthProviderResponseMode | Unset = UNSET,
+
+) -> Response[AuthLinkOAuthProviderResponse200 | Error]:
+ """ Link OAuth provider to current user
+
+ Generates authorization URL to link OAuth provider to existing account.
+ User must be authenticated.
+
+ Args:
+ provider (AuthLinkOAuthProviderProvider):
+ redirect_url (str | Unset):
+ client_state (str | Unset):
+ response_mode (AuthLinkOAuthProviderResponseMode | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthLinkOAuthProviderResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+redirect_url=redirect_url,
+client_state=client_state,
+response_mode=response_mode,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: AuthLinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthLinkOAuthProviderResponseMode | Unset = UNSET,
+
+) -> AuthLinkOAuthProviderResponse200 | Error | None:
+ """ Link OAuth provider to current user
+
+ Generates authorization URL to link OAuth provider to existing account.
+ User must be authenticated.
+
+ Args:
+ provider (AuthLinkOAuthProviderProvider):
+ redirect_url (str | Unset):
+ client_state (str | Unset):
+ response_mode (AuthLinkOAuthProviderResponseMode | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthLinkOAuthProviderResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+redirect_url=redirect_url,
+client_state=client_state,
+response_mode=response_mode,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_list_o_auth_providers.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_list_o_auth_providers.py
new file mode 100644
index 00000000..fc5c502d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_list_o_auth_providers.py
@@ -0,0 +1,166 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_list_o_auth_providers_response_200 import AuthListOAuthProvidersResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/oauth/providers",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> AuthListOAuthProvidersResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = AuthListOAuthProvidersResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[AuthListOAuthProvidersResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthListOAuthProvidersResponse200 | Error]:
+ """ List user's linked providers
+
+ Get list of OAuth providers linked to current user
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthListOAuthProvidersResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthListOAuthProvidersResponse200 | Error | None:
+ """ List user's linked providers
+
+ Get list of OAuth providers linked to current user
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthListOAuthProvidersResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[AuthListOAuthProvidersResponse200 | Error]:
+ """ List user's linked providers
+
+ Get list of OAuth providers linked to current user
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[AuthListOAuthProvidersResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> AuthListOAuthProvidersResponse200 | Error | None:
+ """ List user's linked providers
+
+ Get list of OAuth providers linked to current user
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ AuthListOAuthProvidersResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_authorize.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_authorize.py
new file mode 100644
index 00000000..de744870
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_authorize.py
@@ -0,0 +1,181 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_o_auth_authorize_provider import AuthOAuthAuthorizeProvider
+from ...models.auth_o_auth_authorize_provider import check_auth_o_auth_authorize_provider
+from ...models.auth_o_auth_authorize_response_mode import AuthOAuthAuthorizeResponseMode
+from ...models.auth_o_auth_authorize_response_mode import check_auth_o_auth_authorize_response_mode
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: AuthOAuthAuthorizeProvider,
+ *,
+ anon_key: str,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthOAuthAuthorizeResponseMode | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["anon_key"] = anon_key
+
+ params["redirect_url"] = redirect_url
+
+ params["client_state"] = client_state
+
+ json_response_mode: str | Unset = UNSET
+ if not isinstance(response_mode, Unset):
+ json_response_mode = response_mode
+
+ params["response_mode"] = json_response_mode
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/oauth/{provider}/authorize".format(provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 307:
+ return None
+
+ if response.status_code == 400:
+ return None
+
+ if response.status_code == 404:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: AuthOAuthAuthorizeProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ anon_key: str,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthOAuthAuthorizeResponseMode | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Start OAuth authorization
+
+ Redirects user to OAuth provider for authorization.
+ Handles CSRF protection with state parameter.
+ Project is identified via the anon_key query parameter.
+
+ Args:
+ provider (AuthOAuthAuthorizeProvider):
+ anon_key (str):
+ redirect_url (str | Unset):
+ client_state (str | Unset):
+ response_mode (AuthOAuthAuthorizeResponseMode | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+anon_key=anon_key,
+redirect_url=redirect_url,
+client_state=client_state,
+response_mode=response_mode,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ provider: AuthOAuthAuthorizeProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ anon_key: str,
+ redirect_url: str | Unset = UNSET,
+ client_state: str | Unset = UNSET,
+ response_mode: AuthOAuthAuthorizeResponseMode | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Start OAuth authorization
+
+ Redirects user to OAuth provider for authorization.
+ Handles CSRF protection with state parameter.
+ Project is identified via the anon_key query parameter.
+
+ Args:
+ provider (AuthOAuthAuthorizeProvider):
+ anon_key (str):
+ redirect_url (str | Unset):
+ client_state (str | Unset):
+ response_mode (AuthOAuthAuthorizeResponseMode | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+anon_key=anon_key,
+redirect_url=redirect_url,
+client_state=client_state,
+response_mode=response_mode,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_callback.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_callback.py
new file mode 100644
index 00000000..381c99a5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_callback.py
@@ -0,0 +1,260 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_o_auth_callback_provider import AuthOAuthCallbackProvider
+from ...models.auth_o_auth_callback_provider import check_auth_o_auth_callback_provider
+from ...models.auth_token_response import AuthTokenResponse
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: AuthOAuthCallbackProvider,
+ *,
+ code: str,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["code"] = code
+
+ params["state"] = state
+
+ params["error"] = error
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/oauth/{provider}/callback".format(provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthTokenResponse | None:
+ if response.status_code == 200:
+ response_200 = AuthTokenResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 201:
+ response_201 = AuthTokenResponse.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 303:
+ response_303 = cast(Any, None)
+ return response_303
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 409:
+ response_409 = cast(Any, None)
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthTokenResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: AuthOAuthCallbackProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ code: str,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ OAuth callback handler
+
+ Handles OAuth provider callback with authorization code.
+ Exchanges code for tokens and creates/signs in user.
+
+ Args:
+ provider (AuthOAuthCallbackProvider):
+ code (str):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+code=code,
+state=state,
+error=error,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: AuthOAuthCallbackProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ code: str,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Any | AuthTokenResponse | None:
+ """ OAuth callback handler
+
+ Handles OAuth provider callback with authorization code.
+ Exchanges code for tokens and creates/signs in user.
+
+ Args:
+ provider (AuthOAuthCallbackProvider):
+ code (str):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+code=code,
+state=state,
+error=error,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: AuthOAuthCallbackProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ code: str,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ OAuth callback handler
+
+ Handles OAuth provider callback with authorization code.
+ Exchanges code for tokens and creates/signs in user.
+
+ Args:
+ provider (AuthOAuthCallbackProvider):
+ code (str):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+code=code,
+state=state,
+error=error,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: AuthOAuthCallbackProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ code: str,
+ state: str,
+ error: str | Unset = UNSET,
+
+) -> Any | AuthTokenResponse | None:
+ """ OAuth callback handler
+
+ Handles OAuth provider callback with authorization code.
+ Exchanges code for tokens and creates/signs in user.
+
+ Args:
+ provider (AuthOAuthCallbackProvider):
+ code (str):
+ state (str):
+ error (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+code=code,
+state=state,
+error=error,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_exchange.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_exchange.py
new file mode 100644
index 00000000..025ade93
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_o_auth_exchange.py
@@ -0,0 +1,210 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_o_auth_exchange_body import AuthOAuthExchangeBody
+from ...models.auth_token_response import AuthTokenResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthOAuthExchangeBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/oauth/exchange",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | AuthTokenResponse | None:
+ if response.status_code == 200:
+ response_200 = AuthTokenResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = cast(Any, None)
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = cast(Any, None)
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | AuthTokenResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthOAuthExchangeBody,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ Exchange OAuth authorization code
+
+ Atomically consumes a short-lived callback code and returns the user's
+ session. The request must use the same project anon key and exact
+ redirect_url that initiated the flow.
+
+ Args:
+ body (AuthOAuthExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthOAuthExchangeBody,
+
+) -> Any | AuthTokenResponse | None:
+ """ Exchange OAuth authorization code
+
+ Atomically consumes a short-lived callback code and returns the user's
+ session. The request must use the same project anon key and exact
+ redirect_url that initiated the flow.
+
+ Args:
+ body (AuthOAuthExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthOAuthExchangeBody,
+
+) -> Response[Any | AuthTokenResponse]:
+ """ Exchange OAuth authorization code
+
+ Atomically consumes a short-lived callback code and returns the user's
+ session. The request must use the same project anon key and exact
+ redirect_url that initiated the flow.
+
+ Args:
+ body (AuthOAuthExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | AuthTokenResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthOAuthExchangeBody,
+
+) -> Any | AuthTokenResponse | None:
+ """ Exchange OAuth authorization code
+
+ Atomically consumes a short-lived callback code and returns the user's
+ session. The request must use the same project anon key and exact
+ redirect_url that initiated the flow.
+
+ Args:
+ body (AuthOAuthExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | AuthTokenResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_platform_exchange.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_platform_exchange.py
new file mode 100644
index 00000000..bbc5a5a2
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_platform_exchange.py
@@ -0,0 +1,202 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_platform_exchange_body import AuthPlatformExchangeBody
+from ...models.error import Error
+from ...models.platform_exchange_response import PlatformExchangeResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: AuthPlatformExchangeBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/platform/exchange",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PlatformExchangeResponse | None:
+ if response.status_code == 200:
+ response_200 = PlatformExchangeResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PlatformExchangeResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthPlatformExchangeBody,
+
+) -> Response[Error | PlatformExchangeResponse]:
+ """ Exchange auth-user device session for platform token
+
+ Exchanges a verified auth-user device-flow session into a platform token for CLI usage.
+ The target platform user is derived from authenticated auth-user mapping; client cannot select
+ another user.
+
+ Args:
+ body (AuthPlatformExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PlatformExchangeResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: AuthPlatformExchangeBody,
+
+) -> Error | PlatformExchangeResponse | None:
+ """ Exchange auth-user device session for platform token
+
+ Exchanges a verified auth-user device-flow session into a platform token for CLI usage.
+ The target platform user is derived from authenticated auth-user mapping; client cannot select
+ another user.
+
+ Args:
+ body (AuthPlatformExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PlatformExchangeResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: AuthPlatformExchangeBody,
+
+) -> Response[Error | PlatformExchangeResponse]:
+ """ Exchange auth-user device session for platform token
+
+ Exchanges a verified auth-user device-flow session into a platform token for CLI usage.
+ The target platform user is derived from authenticated auth-user mapping; client cannot select
+ another user.
+
+ Args:
+ body (AuthPlatformExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PlatformExchangeResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: AuthPlatformExchangeBody,
+
+) -> Error | PlatformExchangeResponse | None:
+ """ Exchange auth-user device session for platform token
+
+ Exchanges a verified auth-user device-flow session into a platform token for CLI usage.
+ The target platform user is derived from authenticated auth-user mapping; client cannot select
+ another user.
+
+ Args:
+ body (AuthPlatformExchangeBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PlatformExchangeResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/auth_unlink_o_auth_provider.py b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_unlink_o_auth_provider.py
new file mode 100644
index 00000000..74e0a31a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/auth_unlink_o_auth_provider.py
@@ -0,0 +1,203 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.auth_unlink_o_auth_provider_provider import AuthUnlinkOAuthProviderProvider
+from ...models.auth_unlink_o_auth_provider_provider import check_auth_unlink_o_auth_provider_provider
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: AuthUnlinkOAuthProviderProvider,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/auth/oauth/{provider}/unlink".format(provider=quote(str(provider), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: AuthUnlinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Unlink OAuth provider
+
+ Remove OAuth provider from user's account.
+ Cannot unlink if it's the only authentication method.
+
+ Args:
+ provider (AuthUnlinkOAuthProviderProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: AuthUnlinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Unlink OAuth provider
+
+ Remove OAuth provider from user's account.
+ Cannot unlink if it's the only authentication method.
+
+ Args:
+ provider (AuthUnlinkOAuthProviderProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: AuthUnlinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Unlink OAuth provider
+
+ Remove OAuth provider from user's account.
+ Cannot unlink if it's the only authentication method.
+
+ Args:
+ provider (AuthUnlinkOAuthProviderProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: AuthUnlinkOAuthProviderProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Unlink OAuth provider
+
+ Remove OAuth provider from user's account.
+ Cannot unlink if it's the only authentication method.
+
+ Args:
+ provider (AuthUnlinkOAuthProviderProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/call_o_auth_provider_api.py b/src/volcano_sdk/_generated/api/o_auth_authentication/call_o_auth_provider_api.py
new file mode 100644
index 00000000..ddfa8bd4
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/call_o_auth_provider_api.py
@@ -0,0 +1,279 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.call_o_auth_provider_api_body import CallOAuthProviderAPIBody
+from ...models.call_o_auth_provider_api_provider import CallOAuthProviderAPIProvider
+from ...models.call_o_auth_provider_api_provider import check_call_o_auth_provider_api_provider
+from ...models.call_o_auth_provider_api_response_200 import CallOAuthProviderAPIResponse200
+from ...models.error import Error
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: CallOAuthProviderAPIProvider,
+ *,
+ body: CallOAuthProviderAPIBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/oauth/{provider}/call-api".format(provider=quote(str(provider), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> CallOAuthProviderAPIResponse200 | Error | None:
+ if response.status_code == 200:
+ response_200 = CallOAuthProviderAPIResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 502:
+ response_502 = Error.from_dict(response.json())
+
+
+
+ return response_502
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[CallOAuthProviderAPIResponse200 | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: CallOAuthProviderAPIProvider,
+ *,
+ client: AuthenticatedClient,
+ body: CallOAuthProviderAPIBody,
+
+) -> Response[CallOAuthProviderAPIResponse200 | Error]:
+ """ Call OAuth provider API
+
+ Make an authenticated request to an OAuth provider's API on behalf of the user.
+ The user's stored access token is automatically used and refreshed if needed.
+
+ The request is always sent to the provider's fixed API base URL joined with
+ the caller-supplied `endpoint`. `endpoint` must be a relative path beginning
+ with `/` (optionally with a query string); it cannot change the target host.
+ Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are
+ rejected with `400` so the request can never be redirected to another host.
+
+ Examples of `endpoint`:
+ - Google userinfo: `/oauth2/v1/userinfo`
+ - GitHub repositories: `/user/repos`
+ - Microsoft Graph profile: `/me`
+
+ The response is the raw JSON response from the provider's API.
+
+ Args:
+ provider (CallOAuthProviderAPIProvider):
+ body (CallOAuthProviderAPIBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CallOAuthProviderAPIResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: CallOAuthProviderAPIProvider,
+ *,
+ client: AuthenticatedClient,
+ body: CallOAuthProviderAPIBody,
+
+) -> CallOAuthProviderAPIResponse200 | Error | None:
+ """ Call OAuth provider API
+
+ Make an authenticated request to an OAuth provider's API on behalf of the user.
+ The user's stored access token is automatically used and refreshed if needed.
+
+ The request is always sent to the provider's fixed API base URL joined with
+ the caller-supplied `endpoint`. `endpoint` must be a relative path beginning
+ with `/` (optionally with a query string); it cannot change the target host.
+ Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are
+ rejected with `400` so the request can never be redirected to another host.
+
+ Examples of `endpoint`:
+ - Google userinfo: `/oauth2/v1/userinfo`
+ - GitHub repositories: `/user/repos`
+ - Microsoft Graph profile: `/me`
+
+ The response is the raw JSON response from the provider's API.
+
+ Args:
+ provider (CallOAuthProviderAPIProvider):
+ body (CallOAuthProviderAPIBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CallOAuthProviderAPIResponse200 | Error
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: CallOAuthProviderAPIProvider,
+ *,
+ client: AuthenticatedClient,
+ body: CallOAuthProviderAPIBody,
+
+) -> Response[CallOAuthProviderAPIResponse200 | Error]:
+ """ Call OAuth provider API
+
+ Make an authenticated request to an OAuth provider's API on behalf of the user.
+ The user's stored access token is automatically used and refreshed if needed.
+
+ The request is always sent to the provider's fixed API base URL joined with
+ the caller-supplied `endpoint`. `endpoint` must be a relative path beginning
+ with `/` (optionally with a query string); it cannot change the target host.
+ Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are
+ rejected with `400` so the request can never be redirected to another host.
+
+ Examples of `endpoint`:
+ - Google userinfo: `/oauth2/v1/userinfo`
+ - GitHub repositories: `/user/repos`
+ - Microsoft Graph profile: `/me`
+
+ The response is the raw JSON response from the provider's API.
+
+ Args:
+ provider (CallOAuthProviderAPIProvider):
+ body (CallOAuthProviderAPIBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CallOAuthProviderAPIResponse200 | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: CallOAuthProviderAPIProvider,
+ *,
+ client: AuthenticatedClient,
+ body: CallOAuthProviderAPIBody,
+
+) -> CallOAuthProviderAPIResponse200 | Error | None:
+ """ Call OAuth provider API
+
+ Make an authenticated request to an OAuth provider's API on behalf of the user.
+ The user's stored access token is automatically used and refreshed if needed.
+
+ The request is always sent to the provider's fixed API base URL joined with
+ the caller-supplied `endpoint`. `endpoint` must be a relative path beginning
+ with `/` (optionally with a query string); it cannot change the target host.
+ Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are
+ rejected with `400` so the request can never be redirected to another host.
+
+ Examples of `endpoint`:
+ - Google userinfo: `/oauth2/v1/userinfo`
+ - GitHub repositories: `/user/repos`
+ - Microsoft Graph profile: `/me`
+
+ The response is the raw JSON response from the provider's API.
+
+ Args:
+ provider (CallOAuthProviderAPIProvider):
+ body (CallOAuthProviderAPIBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CallOAuthProviderAPIResponse200 | Error
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/get_o_auth_provider_token.py b/src/volcano_sdk/_generated/api/o_auth_authentication/get_o_auth_provider_token.py
new file mode 100644
index 00000000..fb4c3e9d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/get_o_auth_provider_token.py
@@ -0,0 +1,200 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.get_o_auth_provider_token_provider import check_get_o_auth_provider_token_provider
+from ...models.get_o_auth_provider_token_provider import GetOAuthProviderTokenProvider
+from ...models.get_o_auth_provider_token_response_200 import GetOAuthProviderTokenResponse200
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: GetOAuthProviderTokenProvider,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/auth/oauth/{provider}/token".format(provider=quote(str(provider), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | GetOAuthProviderTokenResponse200 | None:
+ if response.status_code == 200:
+ response_200 = GetOAuthProviderTokenResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | GetOAuthProviderTokenResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: GetOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GetOAuthProviderTokenResponse200]:
+ """ Get current provider access token
+
+ Get valid access token for OAuth provider.
+ Automatically refreshes if expired.
+
+ Args:
+ provider (GetOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GetOAuthProviderTokenResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: GetOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GetOAuthProviderTokenResponse200 | None:
+ """ Get current provider access token
+
+ Get valid access token for OAuth provider.
+ Automatically refreshes if expired.
+
+ Args:
+ provider (GetOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GetOAuthProviderTokenResponse200
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: GetOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | GetOAuthProviderTokenResponse200]:
+ """ Get current provider access token
+
+ Get valid access token for OAuth provider.
+ Automatically refreshes if expired.
+
+ Args:
+ provider (GetOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | GetOAuthProviderTokenResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: GetOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | GetOAuthProviderTokenResponse200 | None:
+ """ Get current provider access token
+
+ Get valid access token for OAuth provider.
+ Automatically refreshes if expired.
+
+ Args:
+ provider (GetOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | GetOAuthProviderTokenResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_authentication/refresh_o_auth_provider_token.py b/src/volcano_sdk/_generated/api/o_auth_authentication/refresh_o_auth_provider_token.py
new file mode 100644
index 00000000..4e78ff57
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_authentication/refresh_o_auth_provider_token.py
@@ -0,0 +1,207 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.refresh_o_auth_provider_token_provider import check_refresh_o_auth_provider_token_provider
+from ...models.refresh_o_auth_provider_token_provider import RefreshOAuthProviderTokenProvider
+from ...models.refresh_o_auth_provider_token_response_200 import RefreshOAuthProviderTokenResponse200
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: RefreshOAuthProviderTokenProvider,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/auth/oauth/{provider}/refresh-token".format(provider=quote(str(provider), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | RefreshOAuthProviderTokenResponse200 | None:
+ if response.status_code == 200:
+ response_200 = RefreshOAuthProviderTokenResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | RefreshOAuthProviderTokenResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: RefreshOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | RefreshOAuthProviderTokenResponse200]:
+ """ Refresh OAuth provider token
+
+ Refresh the access token for an OAuth provider using its refresh token.
+ Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos).
+
+ Args:
+ provider (RefreshOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RefreshOAuthProviderTokenResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: RefreshOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | RefreshOAuthProviderTokenResponse200 | None:
+ """ Refresh OAuth provider token
+
+ Refresh the access token for an OAuth provider using its refresh token.
+ Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos).
+
+ Args:
+ provider (RefreshOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RefreshOAuthProviderTokenResponse200
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: RefreshOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | RefreshOAuthProviderTokenResponse200]:
+ """ Refresh OAuth provider token
+
+ Refresh the access token for an OAuth provider using its refresh token.
+ Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos).
+
+ Args:
+ provider (RefreshOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RefreshOAuthProviderTokenResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: RefreshOAuthProviderTokenProvider,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | RefreshOAuthProviderTokenResponse200 | None:
+ """ Refresh OAuth provider token
+
+ Refresh the access token for an OAuth provider using its refresh token.
+ Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos).
+
+ Args:
+ provider (RefreshOAuthProviderTokenProvider):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RefreshOAuthProviderTokenResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_configuration/__init__.py b/src/volcano_sdk/_generated/api/o_auth_configuration/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_configuration/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/o_auth_configuration/create_o_auth_config.py b/src/volcano_sdk/_generated/api/o_auth_configuration/create_o_auth_config.py
new file mode 100644
index 00000000..04e2586f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_configuration/create_o_auth_config.py
@@ -0,0 +1,204 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_o_auth_config_request import CreateOAuthConfigRequest
+from ...models.o_auth_config import OAuthConfig
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateOAuthConfigRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/oauth/configs".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | OAuthConfig | None:
+ if response.status_code == 201:
+ response_201 = OAuthConfig.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 409:
+ response_409 = cast(Any, None)
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | OAuthConfig]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateOAuthConfigRequest,
+
+) -> Response[Any | OAuthConfig]:
+ """ Create OAuth configuration
+
+ Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device)
+
+ Args:
+ id (UUID):
+ body (CreateOAuthConfigRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | OAuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateOAuthConfigRequest,
+
+) -> Any | OAuthConfig | None:
+ """ Create OAuth configuration
+
+ Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device)
+
+ Args:
+ id (UUID):
+ body (CreateOAuthConfigRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | OAuthConfig
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateOAuthConfigRequest,
+
+) -> Response[Any | OAuthConfig]:
+ """ Create OAuth configuration
+
+ Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device)
+
+ Args:
+ id (UUID):
+ body (CreateOAuthConfigRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | OAuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateOAuthConfigRequest,
+
+) -> Any | OAuthConfig | None:
+ """ Create OAuth configuration
+
+ Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device)
+
+ Args:
+ id (UUID):
+ body (CreateOAuthConfigRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | OAuthConfig
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_configuration/delete_o_auth_config.py b/src/volcano_sdk/_generated/api/o_auth_configuration/delete_o_auth_config.py
new file mode 100644
index 00000000..7a653e83
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_configuration/delete_o_auth_config.py
@@ -0,0 +1,142 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.delete_o_auth_config_provider import check_delete_o_auth_config_provider
+from ...models.delete_o_auth_config_provider import DeleteOAuthConfigProvider
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ provider: DeleteOAuthConfigProvider,
+ *,
+ client_id: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["client_id"] = client_id
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/oauth/configs/{provider}".format(id=quote(str(id), safe=""),provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 204:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ provider: DeleteOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ client_id: str | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Delete OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (DeleteOAuthConfigProvider):
+ client_id (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+provider=provider,
+client_id=client_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ provider: DeleteOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ client_id: str | Unset = UNSET,
+
+) -> Response[Any]:
+ """ Delete OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (DeleteOAuthConfigProvider):
+ client_id (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+provider=provider,
+client_id=client_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/o_auth_configuration/get_o_auth_config.py b/src/volcano_sdk/_generated/api/o_auth_configuration/get_o_auth_config.py
new file mode 100644
index 00000000..a3b3f243
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_configuration/get_o_auth_config.py
@@ -0,0 +1,209 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.get_o_auth_config_provider import check_get_o_auth_config_provider
+from ...models.get_o_auth_config_provider import GetOAuthConfigProvider
+from ...models.o_auth_config import OAuthConfig
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ provider: GetOAuthConfigProvider,
+ *,
+ client_id: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["client_id"] = client_id
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/oauth/configs/{provider}".format(id=quote(str(id), safe=""),provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> OAuthConfig | None:
+ if response.status_code == 200:
+ response_200 = OAuthConfig.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[OAuthConfig]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ provider: GetOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ client_id: str | Unset = UNSET,
+
+) -> Response[OAuthConfig]:
+ """ Get OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (GetOAuthConfigProvider):
+ client_id (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[OAuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+provider=provider,
+client_id=client_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ provider: GetOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ client_id: str | Unset = UNSET,
+
+) -> OAuthConfig | None:
+ """ Get OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (GetOAuthConfigProvider):
+ client_id (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ OAuthConfig
+ """
+
+
+ return sync_detailed(
+ id=id,
+provider=provider,
+client=client,
+client_id=client_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ provider: GetOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ client_id: str | Unset = UNSET,
+
+) -> Response[OAuthConfig]:
+ """ Get OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (GetOAuthConfigProvider):
+ client_id (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[OAuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+provider=provider,
+client_id=client_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ provider: GetOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ client_id: str | Unset = UNSET,
+
+) -> OAuthConfig | None:
+ """ Get OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (GetOAuthConfigProvider):
+ client_id (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ OAuthConfig
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+provider=provider,
+client=client,
+client_id=client_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_configuration/list_available_o_auth_providers.py b/src/volcano_sdk/_generated/api/o_auth_configuration/list_available_o_auth_providers.py
new file mode 100644
index 00000000..693aa0c5
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_configuration/list_available_o_auth_providers.py
@@ -0,0 +1,180 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.list_available_o_auth_providers_response_200 import ListAvailableOAuthProvidersResponse200
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/oauth/providers".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ListAvailableOAuthProvidersResponse200 | None:
+ if response.status_code == 200:
+ response_200 = ListAvailableOAuthProvidersResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ListAvailableOAuthProvidersResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ListAvailableOAuthProvidersResponse200]:
+ """ List available OAuth providers
+
+ Get list of supported OAuth providers and their default scopes
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListAvailableOAuthProvidersResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ListAvailableOAuthProvidersResponse200 | None:
+ """ List available OAuth providers
+
+ Get list of supported OAuth providers and their default scopes
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListAvailableOAuthProvidersResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ListAvailableOAuthProvidersResponse200]:
+ """ List available OAuth providers
+
+ Get list of supported OAuth providers and their default scopes
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListAvailableOAuthProvidersResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ListAvailableOAuthProvidersResponse200 | None:
+ """ List available OAuth providers
+
+ Get list of supported OAuth providers and their default scopes
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListAvailableOAuthProvidersResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_configuration/list_o_auth_configs.py b/src/volcano_sdk/_generated/api/o_auth_configuration/list_o_auth_configs.py
new file mode 100644
index 00000000..c8623271
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_configuration/list_o_auth_configs.py
@@ -0,0 +1,180 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.list_o_auth_configs_response_200 import ListOAuthConfigsResponse200
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/oauth/configs".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ListOAuthConfigsResponse200 | None:
+ if response.status_code == 200:
+ response_200 = ListOAuthConfigsResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ListOAuthConfigsResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ListOAuthConfigsResponse200]:
+ """ List OAuth configurations
+
+ List all OAuth provider configurations for this project
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListOAuthConfigsResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ListOAuthConfigsResponse200 | None:
+ """ List OAuth configurations
+
+ List all OAuth provider configurations for this project
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListOAuthConfigsResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ListOAuthConfigsResponse200]:
+ """ List OAuth configurations
+
+ List all OAuth provider configurations for this project
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListOAuthConfigsResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ListOAuthConfigsResponse200 | None:
+ """ List OAuth configurations
+
+ List all OAuth provider configurations for this project
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListOAuthConfigsResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/o_auth_configuration/update_o_auth_config.py b/src/volcano_sdk/_generated/api/o_auth_configuration/update_o_auth_config.py
new file mode 100644
index 00000000..555333f6
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/o_auth_configuration/update_o_auth_config.py
@@ -0,0 +1,230 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.o_auth_config import OAuthConfig
+from ...models.update_o_auth_config_provider import check_update_o_auth_config_provider
+from ...models.update_o_auth_config_provider import UpdateOAuthConfigProvider
+from ...models.update_o_auth_config_request import UpdateOAuthConfigRequest
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ provider: UpdateOAuthConfigProvider,
+ *,
+ body: UpdateOAuthConfigRequest | Unset = UNSET,
+ client_id: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["client_id"] = client_id
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/oauth/configs/{provider}".format(id=quote(str(id), safe=""),provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ if not isinstance(body, Unset):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> OAuthConfig | None:
+ if response.status_code == 200:
+ response_200 = OAuthConfig.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[OAuthConfig]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ provider: UpdateOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateOAuthConfigRequest | Unset = UNSET,
+ client_id: str | Unset = UNSET,
+
+) -> Response[OAuthConfig]:
+ """ Update OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (UpdateOAuthConfigProvider):
+ client_id (str | Unset):
+ body (UpdateOAuthConfigRequest | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[OAuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+provider=provider,
+body=body,
+client_id=client_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ provider: UpdateOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateOAuthConfigRequest | Unset = UNSET,
+ client_id: str | Unset = UNSET,
+
+) -> OAuthConfig | None:
+ """ Update OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (UpdateOAuthConfigProvider):
+ client_id (str | Unset):
+ body (UpdateOAuthConfigRequest | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ OAuthConfig
+ """
+
+
+ return sync_detailed(
+ id=id,
+provider=provider,
+client=client,
+body=body,
+client_id=client_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ provider: UpdateOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateOAuthConfigRequest | Unset = UNSET,
+ client_id: str | Unset = UNSET,
+
+) -> Response[OAuthConfig]:
+ """ Update OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (UpdateOAuthConfigProvider):
+ client_id (str | Unset):
+ body (UpdateOAuthConfigRequest | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[OAuthConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+provider=provider,
+body=body,
+client_id=client_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ provider: UpdateOAuthConfigProvider,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateOAuthConfigRequest | Unset = UNSET,
+ client_id: str | Unset = UNSET,
+
+) -> OAuthConfig | None:
+ """ Update OAuth configuration
+
+ Args:
+ id (UUID):
+ provider (UpdateOAuthConfigProvider):
+ client_id (str | Unset):
+ body (UpdateOAuthConfigRequest | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ OAuthConfig
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+provider=provider,
+client=client,
+body=body,
+client_id=client_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/__init__.py b/src/volcano_sdk/_generated/api/project_imports/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/project_imports/complete_import_connect.py b/src/volcano_sdk/_generated/api/project_imports/complete_import_connect.py
new file mode 100644
index 00000000..985435bb
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/complete_import_connect.py
@@ -0,0 +1,322 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.import_provider import check_import_provider
+from ...models.import_provider import ImportProvider
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: ImportProvider,
+ *,
+ state: str,
+ code: str | Unset = UNSET,
+ error: str | Unset = UNSET,
+ team_id: str | Unset = UNSET,
+ configuration_id: str | Unset = UNSET,
+ next_: str | Unset = UNSET,
+ source: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["state"] = state
+
+ params["code"] = code
+
+ params["error"] = error
+
+ params["teamId"] = team_id
+
+ params["configurationId"] = configuration_id
+
+ params["next"] = next_
+
+ params["source"] = source
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/imports/{provider}/callback".format(provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 303:
+ response_303 = cast(Any, None)
+ return response_303
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ state: str,
+ code: str | Unset = UNSET,
+ error: str | Unset = UNSET,
+ team_id: str | Unset = UNSET,
+ configuration_id: str | Unset = UNSET,
+ next_: str | Unset = UNSET,
+ source: str | Unset = UNSET,
+
+) -> Response[Any | Error]:
+ """ Complete a project import provider connection
+
+ Public provider callback protected by signed state and the browser-binding
+ cookie created by startImportConnect.
+
+ Args:
+ provider (ImportProvider):
+ state (str):
+ code (str | Unset):
+ error (str | Unset):
+ team_id (str | Unset):
+ configuration_id (str | Unset):
+ next_ (str | Unset):
+ source (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+state=state,
+code=code,
+error=error,
+team_id=team_id,
+configuration_id=configuration_id,
+next_=next_,
+source=source,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ state: str,
+ code: str | Unset = UNSET,
+ error: str | Unset = UNSET,
+ team_id: str | Unset = UNSET,
+ configuration_id: str | Unset = UNSET,
+ next_: str | Unset = UNSET,
+ source: str | Unset = UNSET,
+
+) -> Any | Error | None:
+ """ Complete a project import provider connection
+
+ Public provider callback protected by signed state and the browser-binding
+ cookie created by startImportConnect.
+
+ Args:
+ provider (ImportProvider):
+ state (str):
+ code (str | Unset):
+ error (str | Unset):
+ team_id (str | Unset):
+ configuration_id (str | Unset):
+ next_ (str | Unset):
+ source (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+state=state,
+code=code,
+error=error,
+team_id=team_id,
+configuration_id=configuration_id,
+next_=next_,
+source=source,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ state: str,
+ code: str | Unset = UNSET,
+ error: str | Unset = UNSET,
+ team_id: str | Unset = UNSET,
+ configuration_id: str | Unset = UNSET,
+ next_: str | Unset = UNSET,
+ source: str | Unset = UNSET,
+
+) -> Response[Any | Error]:
+ """ Complete a project import provider connection
+
+ Public provider callback protected by signed state and the browser-binding
+ cookie created by startImportConnect.
+
+ Args:
+ provider (ImportProvider):
+ state (str):
+ code (str | Unset):
+ error (str | Unset):
+ team_id (str | Unset):
+ configuration_id (str | Unset):
+ next_ (str | Unset):
+ source (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+state=state,
+code=code,
+error=error,
+team_id=team_id,
+configuration_id=configuration_id,
+next_=next_,
+source=source,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient | Client,
+ state: str,
+ code: str | Unset = UNSET,
+ error: str | Unset = UNSET,
+ team_id: str | Unset = UNSET,
+ configuration_id: str | Unset = UNSET,
+ next_: str | Unset = UNSET,
+ source: str | Unset = UNSET,
+
+) -> Any | Error | None:
+ """ Complete a project import provider connection
+
+ Public provider callback protected by signed state and the browser-binding
+ cookie created by startImportConnect.
+
+ Args:
+ provider (ImportProvider):
+ state (str):
+ code (str | Unset):
+ error (str | Unset):
+ team_id (str | Unset):
+ configuration_id (str | Unset):
+ next_ (str | Unset):
+ source (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+state=state,
+code=code,
+error=error,
+team_id=team_id,
+configuration_id=configuration_id,
+next_=next_,
+source=source,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/delete_import_connection.py b/src/volcano_sdk/_generated/api/project_imports/delete_import_connection.py
new file mode 100644
index 00000000..ee2bd816
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/delete_import_connection.py
@@ -0,0 +1,211 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ connection_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/user/imports/connections/{connection_id}".format(connection_id=quote(str(connection_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a project import provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a project import provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ connection_id=connection_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a project import provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ connection_id=connection_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ connection_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a project import provider connection
+
+ Args:
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ connection_id=connection_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/get_project_import_run.py b/src/volcano_sdk/_generated/api/project_imports/get_project_import_run.py
new file mode 100644
index 00000000..d7e571c7
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/get_project_import_run.py
@@ -0,0 +1,216 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.import_provider import check_import_provider
+from ...models.import_provider import ImportProvider
+from ...models.project_import_run import ProjectImportRun
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ provider: ImportProvider,
+ run_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/imports/{provider}/runs/{run_id}".format(provider=quote(str(provider), safe=""),run_id=quote(str(run_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectImportRun | None:
+ if response.status_code == 200:
+ response_200 = ProjectImportRun.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectImportRun]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: ImportProvider,
+ run_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectImportRun]:
+ """ Get a project import run
+
+ Args:
+ provider (ImportProvider):
+ run_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectImportRun]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+run_id=run_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: ImportProvider,
+ run_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectImportRun | None:
+ """ Get a project import run
+
+ Args:
+ provider (ImportProvider):
+ run_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectImportRun
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+run_id=run_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: ImportProvider,
+ run_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectImportRun]:
+ """ Get a project import run
+
+ Args:
+ provider (ImportProvider):
+ run_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectImportRun]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+run_id=run_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: ImportProvider,
+ run_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectImportRun | None:
+ """ Get a project import run
+
+ Args:
+ provider (ImportProvider):
+ run_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectImportRun
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+run_id=run_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/list_import_connections.py b/src/volcano_sdk/_generated/api/project_imports/list_import_connections.py
new file mode 100644
index 00000000..7165289e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/list_import_connections.py
@@ -0,0 +1,165 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.import_connections_response import ImportConnectionsResponse
+from typing import cast
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/user/imports/connections",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ImportConnectionsResponse | None:
+ if response.status_code == 200:
+ response_200 = ImportConnectionsResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ImportConnectionsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ImportConnectionsResponse]:
+ """ List project import provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ImportConnectionsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ImportConnectionsResponse | None:
+ """ List project import provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ImportConnectionsResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ImportConnectionsResponse]:
+ """ List project import provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ImportConnectionsResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ImportConnectionsResponse | None:
+ """ List project import provider connections
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ImportConnectionsResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/list_import_sources.py b/src/volcano_sdk/_generated/api/project_imports/list_import_sources.py
new file mode 100644
index 00000000..533bc995
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/list_import_sources.py
@@ -0,0 +1,261 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.import_provider import check_import_provider
+from ...models.import_provider import ImportProvider
+from ...models.import_sources_response import ImportSourcesResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ provider: ImportProvider,
+ *,
+ connection_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_connection_id = str(connection_id)
+ params["connection_id"] = json_connection_id
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/imports/{provider}/sources".format(provider=quote(str(provider), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ImportSourcesResponse | None:
+ if response.status_code == 200:
+ response_200 = ImportSourcesResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ImportSourcesResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ connection_id: UUID,
+
+) -> Response[Error | ImportSourcesResponse]:
+ """ List project sources available from a provider connection
+
+ Lists provider projects without changing provider or Volcano resources.
+
+ Args:
+ provider (ImportProvider):
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ImportSourcesResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+connection_id=connection_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ connection_id: UUID,
+
+) -> Error | ImportSourcesResponse | None:
+ """ List project sources available from a provider connection
+
+ Lists provider projects without changing provider or Volcano resources.
+
+ Args:
+ provider (ImportProvider):
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ImportSourcesResponse
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+connection_id=connection_id,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ connection_id: UUID,
+
+) -> Response[Error | ImportSourcesResponse]:
+ """ List project sources available from a provider connection
+
+ Lists provider projects without changing provider or Volcano resources.
+
+ Args:
+ provider (ImportProvider):
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ImportSourcesResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+connection_id=connection_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ connection_id: UUID,
+
+) -> Error | ImportSourcesResponse | None:
+ """ List project sources available from a provider connection
+
+ Lists provider projects without changing provider or Volcano resources.
+
+ Args:
+ provider (ImportProvider):
+ connection_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ImportSourcesResponse
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+connection_id=connection_id,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/preflight_project_import.py b/src/volcano_sdk/_generated/api/project_imports/preflight_project_import.py
new file mode 100644
index 00000000..cbd70dae
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/preflight_project_import.py
@@ -0,0 +1,258 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.import_provider import check_import_provider
+from ...models.import_provider import ImportProvider
+from ...models.project_import_preflight_request import ProjectImportPreflightRequest
+from ...models.project_import_report import ProjectImportReport
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: ImportProvider,
+ *,
+ body: ProjectImportPreflightRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/imports/{provider}/preflight".format(provider=quote(str(provider), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectImportReport | None:
+ if response.status_code == 200:
+ response_200 = ProjectImportReport.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectImportReport]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportPreflightRequest,
+
+) -> Response[Error | ProjectImportReport]:
+ """ Check whether a provider project is ready to import
+
+ Produces a deterministic read-only readiness report for a proposed new Volcano project.
+
+ Args:
+ provider (ImportProvider):
+ body (ProjectImportPreflightRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectImportReport]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportPreflightRequest,
+
+) -> Error | ProjectImportReport | None:
+ """ Check whether a provider project is ready to import
+
+ Produces a deterministic read-only readiness report for a proposed new Volcano project.
+
+ Args:
+ provider (ImportProvider):
+ body (ProjectImportPreflightRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectImportReport
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportPreflightRequest,
+
+) -> Response[Error | ProjectImportReport]:
+ """ Check whether a provider project is ready to import
+
+ Produces a deterministic read-only readiness report for a proposed new Volcano project.
+
+ Args:
+ provider (ImportProvider):
+ body (ProjectImportPreflightRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectImportReport]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportPreflightRequest,
+
+) -> Error | ProjectImportReport | None:
+ """ Check whether a provider project is ready to import
+
+ Produces a deterministic read-only readiness report for a proposed new Volcano project.
+
+ Args:
+ provider (ImportProvider):
+ body (ProjectImportPreflightRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectImportReport
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/start_import_connect.py b/src/volcano_sdk/_generated/api/project_imports/start_import_connect.py
new file mode 100644
index 00000000..c1f1294d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/start_import_connect.py
@@ -0,0 +1,246 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.import_connect_start_response import ImportConnectStartResponse
+from ...models.import_provider import check_import_provider
+from ...models.import_provider import ImportProvider
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ provider: ImportProvider | Unset = UNSET,
+ redirect: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_provider: str | Unset = UNSET
+ if not isinstance(provider, Unset):
+ json_provider = provider
+
+ params["provider"] = json_provider
+
+ params["redirect"] = redirect
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/user/imports/connect",
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ImportConnectStartResponse | None:
+ if response.status_code == 200:
+ response_200 = ImportConnectStartResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ImportConnectStartResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ provider: ImportProvider | Unset = UNSET,
+ redirect: str | Unset = UNSET,
+
+) -> Response[Error | ImportConnectStartResponse]:
+ """ Start a project import provider connection
+
+ Starts a first-party dashboard user's provider connection flow. The
+ response sets a short-lived HttpOnly browser-binding cookie for the
+ public provider callback.
+
+ Args:
+ provider (ImportProvider | Unset):
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ImportConnectStartResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+redirect=redirect,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ provider: ImportProvider | Unset = UNSET,
+ redirect: str | Unset = UNSET,
+
+) -> Error | ImportConnectStartResponse | None:
+ """ Start a project import provider connection
+
+ Starts a first-party dashboard user's provider connection flow. The
+ response sets a short-lived HttpOnly browser-binding cookie for the
+ public provider callback.
+
+ Args:
+ provider (ImportProvider | Unset):
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ImportConnectStartResponse
+ """
+
+
+ return sync_detailed(
+ client=client,
+provider=provider,
+redirect=redirect,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ provider: ImportProvider | Unset = UNSET,
+ redirect: str | Unset = UNSET,
+
+) -> Response[Error | ImportConnectStartResponse]:
+ """ Start a project import provider connection
+
+ Starts a first-party dashboard user's provider connection flow. The
+ response sets a short-lived HttpOnly browser-binding cookie for the
+ public provider callback.
+
+ Args:
+ provider (ImportProvider | Unset):
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ImportConnectStartResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+redirect=redirect,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ provider: ImportProvider | Unset = UNSET,
+ redirect: str | Unset = UNSET,
+
+) -> Error | ImportConnectStartResponse | None:
+ """ Start a project import provider connection
+
+ Starts a first-party dashboard user's provider connection flow. The
+ response sets a short-lived HttpOnly browser-binding cookie for the
+ public provider callback.
+
+ Args:
+ provider (ImportProvider | Unset):
+ redirect (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ImportConnectStartResponse
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+provider=provider,
+redirect=redirect,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/project_imports/start_project_import.py b/src/volcano_sdk/_generated/api/project_imports/start_project_import.py
new file mode 100644
index 00000000..efb8b392
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/project_imports/start_project_import.py
@@ -0,0 +1,284 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.import_provider import check_import_provider
+from ...models.import_provider import ImportProvider
+from ...models.project_import_run import ProjectImportRun
+from ...models.project_import_start_request import ProjectImportStartRequest
+from typing import cast
+
+
+
+def _get_kwargs(
+ provider: ImportProvider,
+ *,
+ body: ProjectImportStartRequest,
+ idempotency_key: str,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["Idempotency-Key"] = idempotency_key
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/imports/{provider}/runs".format(provider=quote(str(provider), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectImportRun | None:
+ if response.status_code == 202:
+ response_202 = ProjectImportRun.from_dict(response.json())
+
+
+
+ return response_202
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 422:
+ response_422 = Error.from_dict(response.json())
+
+
+
+ return response_422
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectImportRun]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportStartRequest,
+ idempotency_key: str,
+
+) -> Response[Error | ProjectImportRun]:
+ """ Start a Vercel project import
+
+ Creates a Volcano project from an importable production preflight report. Retrying the same request
+ with the same Idempotency-Key returns the existing run.
+
+ Args:
+ provider (ImportProvider):
+ idempotency_key (str):
+ body (ProjectImportStartRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectImportRun]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+body=body,
+idempotency_key=idempotency_key,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportStartRequest,
+ idempotency_key: str,
+
+) -> Error | ProjectImportRun | None:
+ """ Start a Vercel project import
+
+ Creates a Volcano project from an importable production preflight report. Retrying the same request
+ with the same Idempotency-Key returns the existing run.
+
+ Args:
+ provider (ImportProvider):
+ idempotency_key (str):
+ body (ProjectImportStartRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectImportRun
+ """
+
+
+ return sync_detailed(
+ provider=provider,
+client=client,
+body=body,
+idempotency_key=idempotency_key,
+
+ ).parsed
+
+async def asyncio_detailed(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportStartRequest,
+ idempotency_key: str,
+
+) -> Response[Error | ProjectImportRun]:
+ """ Start a Vercel project import
+
+ Creates a Volcano project from an importable production preflight report. Retrying the same request
+ with the same Idempotency-Key returns the existing run.
+
+ Args:
+ provider (ImportProvider):
+ idempotency_key (str):
+ body (ProjectImportStartRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectImportRun]
+ """
+
+
+ kwargs = _get_kwargs(
+ provider=provider,
+body=body,
+idempotency_key=idempotency_key,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ provider: ImportProvider,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectImportStartRequest,
+ idempotency_key: str,
+
+) -> Error | ProjectImportRun | None:
+ """ Start a Vercel project import
+
+ Creates a Volcano project from an importable production preflight report. Retrying the same request
+ with the same Idempotency-Key returns the existing run.
+
+ Args:
+ provider (ImportProvider):
+ idempotency_key (str):
+ body (ProjectImportStartRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectImportRun
+ """
+
+
+ return (await asyncio_detailed(
+ provider=provider,
+client=client,
+body=body,
+idempotency_key=idempotency_key,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/__init__.py b/src/volcano_sdk/_generated/api/projects/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/projects/apply_project_config.py b/src/volcano_sdk/_generated/api/projects/apply_project_config.py
new file mode 100644
index 00000000..e609dd93
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/apply_project_config.py
@@ -0,0 +1,342 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_config import ProjectConfig
+from ...models.project_config_apply_result import ProjectConfigApplyResult
+from ...models.project_config_validation_error_response import ProjectConfigValidationErrorResponse
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: ProjectConfig,
+ dry_run: bool | Unset = False,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["dry_run"] = dry_run
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/config".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse | None:
+ if response.status_code == 200:
+ response_200 = ProjectConfigApplyResult.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 422:
+ response_422 = ProjectConfigValidationErrorResponse.from_dict(response.json())
+
+
+
+ return response_422
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectConfig,
+ dry_run: bool | Unset = False,
+
+) -> Response[Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse]:
+ """ Apply project configuration
+
+ Validates and applies a declarative configuration manifest to the
+ project, reconciling each declared section and returning a per-resource
+ report. Omitted sections are untouched. Declared collection keys
+ (`variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, `functions[].schedulers`) are fully synced:
+ resources absent from the manifest are deleted. Functions, frontends,
+ databases, and buckets are never created or deleted; manifest entries
+ for resources that do not exist are skipped and reported in `skipped`,
+ and existing resources missing from a declared section are reported in
+ `missing`. Validation failures (including plan-gate violations) return
+ 422 and nothing is applied. Set `dry_run=true` to get the projected
+ report without applying changes. Applies are serialized per project;
+ a concurrent apply returns 409.
+
+ Args:
+ id (UUID):
+ dry_run (bool | Unset): Default: False.
+ body (ProjectConfig): Declarative project configuration manifest (the JSON form of
+ volcano-config.yaml). Omitted sections are left untouched. Within
+ declared entries, omitted optional fields keep their current server
+ values (patch semantics). Declared collection keys are fully synced to
+ the manifest: `variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, and `functions[].schedulers` are reconciled to
+ exactly match, deleting resources absent from the manifest. Functions,
+ frontends, databases, and buckets are never created or deleted through
+ this manifest; entries referencing resources that do not exist are
+ skipped and reported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+dry_run=dry_run,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectConfig,
+ dry_run: bool | Unset = False,
+
+) -> Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse | None:
+ """ Apply project configuration
+
+ Validates and applies a declarative configuration manifest to the
+ project, reconciling each declared section and returning a per-resource
+ report. Omitted sections are untouched. Declared collection keys
+ (`variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, `functions[].schedulers`) are fully synced:
+ resources absent from the manifest are deleted. Functions, frontends,
+ databases, and buckets are never created or deleted; manifest entries
+ for resources that do not exist are skipped and reported in `skipped`,
+ and existing resources missing from a declared section are reported in
+ `missing`. Validation failures (including plan-gate violations) return
+ 422 and nothing is applied. Set `dry_run=true` to get the projected
+ report without applying changes. Applies are serialized per project;
+ a concurrent apply returns 409.
+
+ Args:
+ id (UUID):
+ dry_run (bool | Unset): Default: False.
+ body (ProjectConfig): Declarative project configuration manifest (the JSON form of
+ volcano-config.yaml). Omitted sections are left untouched. Within
+ declared entries, omitted optional fields keep their current server
+ values (patch semantics). Declared collection keys are fully synced to
+ the manifest: `variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, and `functions[].schedulers` are reconciled to
+ exactly match, deleting resources absent from the manifest. Functions,
+ frontends, databases, and buckets are never created or deleted through
+ this manifest; entries referencing resources that do not exist are
+ skipped and reported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+dry_run=dry_run,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectConfig,
+ dry_run: bool | Unset = False,
+
+) -> Response[Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse]:
+ """ Apply project configuration
+
+ Validates and applies a declarative configuration manifest to the
+ project, reconciling each declared section and returning a per-resource
+ report. Omitted sections are untouched. Declared collection keys
+ (`variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, `functions[].schedulers`) are fully synced:
+ resources absent from the manifest are deleted. Functions, frontends,
+ databases, and buckets are never created or deleted; manifest entries
+ for resources that do not exist are skipped and reported in `skipped`,
+ and existing resources missing from a declared section are reported in
+ `missing`. Validation failures (including plan-gate violations) return
+ 422 and nothing is applied. Set `dry_run=true` to get the projected
+ report without applying changes. Applies are serialized per project;
+ a concurrent apply returns 409.
+
+ Args:
+ id (UUID):
+ dry_run (bool | Unset): Default: False.
+ body (ProjectConfig): Declarative project configuration manifest (the JSON form of
+ volcano-config.yaml). Omitted sections are left untouched. Within
+ declared entries, omitted optional fields keep their current server
+ values (patch semantics). Declared collection keys are fully synced to
+ the manifest: `variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, and `functions[].schedulers` are reconciled to
+ exactly match, deleting resources absent from the manifest. Functions,
+ frontends, databases, and buckets are never created or deleted through
+ this manifest; entries referencing resources that do not exist are
+ skipped and reported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+dry_run=dry_run,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectConfig,
+ dry_run: bool | Unset = False,
+
+) -> Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse | None:
+ """ Apply project configuration
+
+ Validates and applies a declarative configuration manifest to the
+ project, reconciling each declared section and returning a per-resource
+ report. Omitted sections are untouched. Declared collection keys
+ (`variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, `functions[].schedulers`) are fully synced:
+ resources absent from the manifest are deleted. Functions, frontends,
+ databases, and buckets are never created or deleted; manifest entries
+ for resources that do not exist are skipped and reported in `skipped`,
+ and existing resources missing from a declared section are reported in
+ `missing`. Validation failures (including plan-gate violations) return
+ 422 and nothing is applied. Set `dry_run=true` to get the projected
+ report without applying changes. Applies are serialized per project;
+ a concurrent apply returns 409.
+
+ Args:
+ id (UUID):
+ dry_run (bool | Unset): Default: False.
+ body (ProjectConfig): Declarative project configuration manifest (the JSON form of
+ volcano-config.yaml). Omitted sections are left untouched. Within
+ declared entries, omitted optional fields keep their current server
+ values (patch semantics). Declared collection keys are fully synced to
+ the manifest: `variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, and `functions[].schedulers` are reconciled to
+ exactly match, deleting resources absent from the manifest. Functions,
+ frontends, databases, and buckets are never created or deleted through
+ this manifest; entries referencing resources that do not exist are
+ skipped and reported.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectConfigApplyResult | ProjectConfigValidationErrorResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+dry_run=dry_run,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/connect_project_git.py b/src/volcano_sdk/_generated/api/projects/connect_project_git.py
new file mode 100644
index 00000000..b06b72c0
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/connect_project_git.py
@@ -0,0 +1,271 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.connect_project_git_request import ConnectProjectGitRequest
+from ...models.error import Error
+from ...models.project_git_connection import ProjectGitConnection
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: ConnectProjectGitRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/git-connection".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectGitConnection | None:
+ if response.status_code == 200:
+ response_200 = ProjectGitConnection.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectGitConnection]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ConnectProjectGitRequest,
+
+) -> Response[Error | ProjectGitConnection]:
+ """ Connect or update a project's repo connection
+
+ Full replace, following Vercel's model: many projects may point at the
+ same repo, so this only binds the project — it never creates or
+ deletes git-provider state. Used for both the initial connect and
+ later edits (repo change, root directory, production branch).
+ Resolves the repository_id or repo_full_name selector against the repos
+ accessible through installation_id via connection_id's stored GitHub
+ user token, then persists repository metadata only from that validated
+ GitHub response.
+
+ Args:
+ id (UUID):
+ body (ConnectProjectGitRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitConnection]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ConnectProjectGitRequest,
+
+) -> Error | ProjectGitConnection | None:
+ """ Connect or update a project's repo connection
+
+ Full replace, following Vercel's model: many projects may point at the
+ same repo, so this only binds the project — it never creates or
+ deletes git-provider state. Used for both the initial connect and
+ later edits (repo change, root directory, production branch).
+ Resolves the repository_id or repo_full_name selector against the repos
+ accessible through installation_id via connection_id's stored GitHub
+ user token, then persists repository metadata only from that validated
+ GitHub response.
+
+ Args:
+ id (UUID):
+ body (ConnectProjectGitRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitConnection
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ConnectProjectGitRequest,
+
+) -> Response[Error | ProjectGitConnection]:
+ """ Connect or update a project's repo connection
+
+ Full replace, following Vercel's model: many projects may point at the
+ same repo, so this only binds the project — it never creates or
+ deletes git-provider state. Used for both the initial connect and
+ later edits (repo change, root directory, production branch).
+ Resolves the repository_id or repo_full_name selector against the repos
+ accessible through installation_id via connection_id's stored GitHub
+ user token, then persists repository metadata only from that validated
+ GitHub response.
+
+ Args:
+ id (UUID):
+ body (ConnectProjectGitRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitConnection]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ConnectProjectGitRequest,
+
+) -> Error | ProjectGitConnection | None:
+ """ Connect or update a project's repo connection
+
+ Full replace, following Vercel's model: many projects may point at the
+ same repo, so this only binds the project — it never creates or
+ deletes git-provider state. Used for both the initial connect and
+ later edits (repo change, root directory, production branch).
+ Resolves the repository_id or repo_full_name selector against the repos
+ accessible through installation_id via connection_id's stored GitHub
+ user token, then persists repository metadata only from that validated
+ GitHub response.
+
+ Args:
+ id (UUID):
+ body (ConnectProjectGitRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitConnection
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/create_project.py b/src/volcano_sdk/_generated/api/projects/create_project.py
new file mode 100644
index 00000000..9afbd30c
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/create_project.py
@@ -0,0 +1,205 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_project_request import CreateProjectRequest
+from ...models.error import Error
+from ...models.project import Project
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ body: CreateProjectRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects",
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Project | None:
+ if response.status_code == 201:
+ response_201 = Project.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Project]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: CreateProjectRequest,
+
+) -> Response[Error | Project]:
+ """ Create a new project
+
+ Creates a project for the authenticated user.
+ Each user can create up to 1,000 projects. Requests over this cap return 403.
+
+ Args:
+ body (CreateProjectRequest): Request to create a new project
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ body: CreateProjectRequest,
+
+) -> Error | Project | None:
+ """ Create a new project
+
+ Creates a project for the authenticated user.
+ Each user can create up to 1,000 projects. Requests over this cap return 403.
+
+ Args:
+ body (CreateProjectRequest): Request to create a new project
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return sync_detailed(
+ client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ body: CreateProjectRequest,
+
+) -> Response[Error | Project]:
+ """ Create a new project
+
+ Creates a project for the authenticated user.
+ Each user can create up to 1,000 projects. Requests over this cap return 403.
+
+ Args:
+ body (CreateProjectRequest): Request to create a new project
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ body: CreateProjectRequest,
+
+) -> Error | Project | None:
+ """ Create a new project
+
+ Creates a project for the authenticated user.
+ Each user can create up to 1,000 projects. Requests over this cap return 403.
+
+ Args:
+ body (CreateProjectRequest): Request to create a new project
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/delete_project.py b/src/volcano_sdk/_generated/api/projects/delete_project.py
new file mode 100644
index 00000000..fbfe71c2
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/delete_project.py
@@ -0,0 +1,196 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 202:
+ response_202 = cast(Any, None)
+ return response_202
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a project
+
+ Starts asynchronous project deletion. The project remains available from
+ `GET /projects/{id}` with `status: deleting` until cleanup finishes, but is
+ removed from project lists as soon as deletion starts. After cleanup it
+ returns 404.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a project
+
+ Starts asynchronous project deletion. The project remains available from
+ `GET /projects/{id}` with `status: deleting` until cleanup finishes, but is
+ removed from project lists as soon as deletion starts. After cleanup it
+ returns 404.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a project
+
+ Starts asynchronous project deletion. The project remains available from
+ `GET /projects/{id}` with `status: deleting` until cleanup finishes, but is
+ removed from project lists as soon as deletion starts. After cleanup it
+ returns 404.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a project
+
+ Starts asynchronous project deletion. The project remains available from
+ `GET /projects/{id}` with `status: deleting` until cleanup finishes, but is
+ removed from project lists as soon as deletion starts. After cleanup it
+ returns 404.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/delete_project_logo.py b/src/volcano_sdk/_generated/api/projects/delete_project_logo.py
new file mode 100644
index 00000000..6e75b2ee
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/delete_project_logo.py
@@ -0,0 +1,213 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project import Project
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/logo".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Project | None:
+ if response.status_code == 200:
+ response_200 = Project.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Project]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Project]:
+ """ Remove the project logo
+
+ Deletes the project logo from the project's storage folder and clears its
+ record. Returns the updated project with no `logo_url`.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Project | None:
+ """ Remove the project logo
+
+ Deletes the project logo from the project's storage folder and clears its
+ record. Returns the updated project with no `logo_url`.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Project]:
+ """ Remove the project logo
+
+ Deletes the project logo from the project's storage folder and clears its
+ record. Returns the updated project with no `logo_url`.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Project | None:
+ """ Remove the project logo
+
+ Deletes the project logo from the project's storage folder and clears its
+ record. Returns the updated project with no `logo_url`.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/disconnect_project_git.py b/src/volcano_sdk/_generated/api/projects/disconnect_project_git.py
new file mode 100644
index 00000000..95a539a4
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/disconnect_project_git.py
@@ -0,0 +1,197 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/git-connection".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Disconnect a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Disconnect a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Disconnect a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Disconnect a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/get_project.py b/src/volcano_sdk/_generated/api/projects/get_project.py
new file mode 100644
index 00000000..1997ce0b
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/get_project.py
@@ -0,0 +1,180 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project import Project
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Project | None:
+ if response.status_code == 200:
+ response_200 = Project.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Project]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Project]:
+ """ Get project by ID
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Project | None:
+ """ Get project by ID
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Project]:
+ """ Get project by ID
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Project | None:
+ """ Get project by ID
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/get_project_config.py b/src/volcano_sdk/_generated/api/projects/get_project_config.py
new file mode 100644
index 00000000..6bf27fc8
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/get_project_config.py
@@ -0,0 +1,251 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.get_project_config_format import check_get_project_config_format
+from ...models.get_project_config_format import GetProjectConfigFormat
+from ...models.project_config import ProjectConfig
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ format_: GetProjectConfigFormat | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_format_: str | Unset = UNSET
+ if not isinstance(format_, Unset):
+ json_format_ = format_
+
+ params["format"] = json_format_
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/config".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectConfig | None:
+ if response.status_code == 200:
+ response_200 = ProjectConfig.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectConfig]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ format_: GetProjectConfigFormat | Unset = UNSET,
+
+) -> Response[Error | ProjectConfig]:
+ """ Export project configuration
+
+ Exports the project's current user-facing configuration as a
+ declarative manifest. Returns JSON by default. Request the canonical
+ volcano-config.yaml rendering with `Accept: application/yaml` or
+ `?format=yaml`; the YAML is returned verbatim as the raw response body
+ (`Content-Type: application/yaml`) and is meant to be saved as-is.
+ Write-only secrets (SMTP password, OAuth client secrets, TLS material)
+ are omitted from the export; the YAML rendering adds a header comment
+ describing how to set them via CLI environment interpolation.
+
+ Args:
+ id (UUID):
+ format_ (GetProjectConfigFormat | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+format_=format_,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ format_: GetProjectConfigFormat | Unset = UNSET,
+
+) -> Error | ProjectConfig | None:
+ """ Export project configuration
+
+ Exports the project's current user-facing configuration as a
+ declarative manifest. Returns JSON by default. Request the canonical
+ volcano-config.yaml rendering with `Accept: application/yaml` or
+ `?format=yaml`; the YAML is returned verbatim as the raw response body
+ (`Content-Type: application/yaml`) and is meant to be saved as-is.
+ Write-only secrets (SMTP password, OAuth client secrets, TLS material)
+ are omitted from the export; the YAML rendering adds a header comment
+ describing how to set them via CLI environment interpolation.
+
+ Args:
+ id (UUID):
+ format_ (GetProjectConfigFormat | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectConfig
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+format_=format_,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ format_: GetProjectConfigFormat | Unset = UNSET,
+
+) -> Response[Error | ProjectConfig]:
+ """ Export project configuration
+
+ Exports the project's current user-facing configuration as a
+ declarative manifest. Returns JSON by default. Request the canonical
+ volcano-config.yaml rendering with `Accept: application/yaml` or
+ `?format=yaml`; the YAML is returned verbatim as the raw response body
+ (`Content-Type: application/yaml`) and is meant to be saved as-is.
+ Write-only secrets (SMTP password, OAuth client secrets, TLS material)
+ are omitted from the export; the YAML rendering adds a header comment
+ describing how to set them via CLI environment interpolation.
+
+ Args:
+ id (UUID):
+ format_ (GetProjectConfigFormat | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+format_=format_,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ format_: GetProjectConfigFormat | Unset = UNSET,
+
+) -> Error | ProjectConfig | None:
+ """ Export project configuration
+
+ Exports the project's current user-facing configuration as a
+ declarative manifest. Returns JSON by default. Request the canonical
+ volcano-config.yaml rendering with `Accept: application/yaml` or
+ `?format=yaml`; the YAML is returned verbatim as the raw response body
+ (`Content-Type: application/yaml`) and is meant to be saved as-is.
+ Write-only secrets (SMTP password, OAuth client secrets, TLS material)
+ are omitted from the export; the YAML rendering adds a header comment
+ describing how to set them via CLI environment interpolation.
+
+ Args:
+ id (UUID):
+ format_ (GetProjectConfigFormat | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectConfig
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+format_=format_,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/get_project_git_connection.py b/src/volcano_sdk/_generated/api/projects/get_project_git_connection.py
new file mode 100644
index 00000000..6d3a7ada
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/get_project_git_connection.py
@@ -0,0 +1,201 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_git_connection import ProjectGitConnection
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/git-connection".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectGitConnection | None:
+ if response.status_code == 200:
+ response_200 = ProjectGitConnection.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectGitConnection]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectGitConnection]:
+ """ Get a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitConnection]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectGitConnection | None:
+ """ Get a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitConnection
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectGitConnection]:
+ """ Get a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitConnection]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectGitConnection | None:
+ """ Get a project's repo connection
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitConnection
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/get_project_git_deploy_settings.py b/src/volcano_sdk/_generated/api/projects/get_project_git_deploy_settings.py
new file mode 100644
index 00000000..227ab170
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/get_project_git_deploy_settings.py
@@ -0,0 +1,201 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_git_deploy_settings import ProjectGitDeploySettings
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/git-deploy-settings".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectGitDeploySettings | None:
+ if response.status_code == 200:
+ response_200 = ProjectGitDeploySettings.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectGitDeploySettings]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectGitDeploySettings]:
+ """ Get a project's Git auto-deploy settings
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitDeploySettings]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectGitDeploySettings | None:
+ """ Get a project's Git auto-deploy settings
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitDeploySettings
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectGitDeploySettings]:
+ """ Get a project's Git auto-deploy settings
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitDeploySettings]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectGitDeploySettings | None:
+ """ Get a project's Git auto-deploy settings
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitDeploySettings
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/get_project_health.py b/src/volcano_sdk/_generated/api/projects/get_project_health.py
new file mode 100644
index 00000000..ca321f03
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/get_project_health.py
@@ -0,0 +1,221 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_health_response import ProjectHealthResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/health".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectHealthResponse | None:
+ if response.status_code == 200:
+ response_200 = ProjectHealthResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectHealthResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectHealthResponse]:
+ """ Get project health
+
+ Returns a fast control-plane health snapshot for the project and its
+ deployed resources. The endpoint does not run live provider probes.
+ A successful request returns 200 even when the project status is
+ `unhealthy`; transport and authorization failures use HTTP errors.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectHealthResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectHealthResponse | None:
+ """ Get project health
+
+ Returns a fast control-plane health snapshot for the project and its
+ deployed resources. The endpoint does not run live provider probes.
+ A successful request returns 200 even when the project status is
+ `unhealthy`; transport and authorization failures use HTTP errors.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectHealthResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectHealthResponse]:
+ """ Get project health
+
+ Returns a fast control-plane health snapshot for the project and its
+ deployed resources. The endpoint does not run live provider probes.
+ A successful request returns 200 even when the project status is
+ `unhealthy`; transport and authorization failures use HTTP errors.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectHealthResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectHealthResponse | None:
+ """ Get project health
+
+ Returns a fast control-plane health snapshot for the project and its
+ deployed resources. The endpoint does not run live provider probes.
+ A successful request returns 200 even when the project status is
+ `unhealthy`; transport and authorization failures use HTTP errors.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectHealthResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/get_project_logo.py b/src/volcano_sdk/_generated/api/projects/get_project_logo.py
new file mode 100644
index 00000000..9ac5f430
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/get_project_logo.py
@@ -0,0 +1,196 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/logo".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | None:
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Error]:
+ """ Get the project logo image
+
+ Returns the raw logo image stored in the project's storage folder. This
+ endpoint is unauthenticated so the asset can be rendered directly in an
+ `
` tag; project IDs are unguessable UUIDs and logos are
+ non-sensitive branding. The `Project.logo_url` field exposes a versioned
+ path to this endpoint.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Error | None:
+ """ Get the project logo image
+
+ Returns the raw logo image stored in the project's storage folder. This
+ endpoint is unauthenticated so the asset can be rendered directly in an
+ `
` tag; project IDs are unguessable UUIDs and logos are
+ non-sensitive branding. The `Project.logo_url` field exposes a versioned
+ path to this endpoint.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Error]:
+ """ Get the project logo image
+
+ Returns the raw logo image stored in the project's storage folder. This
+ endpoint is unauthenticated so the asset can be rendered directly in an
+ `
` tag; project IDs are unguessable UUIDs and logos are
+ non-sensitive branding. The `Project.logo_url` field exposes a versioned
+ path to this endpoint.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Error | None:
+ """ Get the project logo image
+
+ Returns the raw logo image stored in the project's storage folder. This
+ endpoint is unauthenticated so the asset can be rendered directly in an
+ `
` tag; project IDs are unguessable UUIDs and logos are
+ non-sensitive branding. The `Project.logo_url` field exposes a versioned
+ path to this endpoint.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/get_project_usage.py b/src/volcano_sdk/_generated/api/projects/get_project_usage.py
new file mode 100644
index 00000000..a271e177
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/get_project_usage.py
@@ -0,0 +1,199 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_usage_response import ProjectUsageResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/usage".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectUsageResponse | None:
+ if response.status_code == 200:
+ response_200 = ProjectUsageResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectUsageResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectUsageResponse]:
+ """ Get usage metrics for a project
+
+ Returns project usage totals for the current usage month plus
+ recent hourly and daily time series for each tracked metric.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectUsageResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectUsageResponse | None:
+ """ Get usage metrics for a project
+
+ Returns project usage totals for the current usage month plus
+ recent hourly and daily time series for each tracked metric.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectUsageResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | ProjectUsageResponse]:
+ """ Get usage metrics for a project
+
+ Returns project usage totals for the current usage month plus
+ recent hourly and daily time series for each tracked metric.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectUsageResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | ProjectUsageResponse | None:
+ """ Get usage metrics for a project
+
+ Returns project usage totals for the current usage month plus
+ recent hourly and daily time series for each tracked metric.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectUsageResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/list_deployments.py b/src/volcano_sdk/_generated/api/projects/list_deployments.py
new file mode 100644
index 00000000..91bdfc4d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/list_deployments.py
@@ -0,0 +1,558 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.list_deployments_operation import check_list_deployments_operation
+from ...models.list_deployments_operation import ListDeploymentsOperation
+from ...models.list_deployments_order import check_list_deployments_order
+from ...models.list_deployments_order import ListDeploymentsOrder
+from ...models.list_deployments_resource_type import check_list_deployments_resource_type
+from ...models.list_deployments_resource_type import ListDeploymentsResourceType
+from ...models.list_deployments_status import check_list_deployments_status
+from ...models.list_deployments_status import ListDeploymentsStatus
+from ...models.paginated_project_deployments import PaginatedProjectDeployments
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+def _get_kwargs(
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ owner_id: str | Unset = UNSET,
+ project_id: UUID | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListDeploymentsResourceType | Unset = UNSET,
+ status: ListDeploymentsStatus | Unset = UNSET,
+ operation: ListDeploymentsOperation | Unset = UNSET,
+ order: ListDeploymentsOrder | Unset = 'created_at.desc',
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["owner_id"] = owner_id
+
+ json_project_id: str | Unset = UNSET
+ if not isinstance(project_id, Unset):
+ json_project_id = str(project_id)
+ params["project_id"] = json_project_id
+
+ json_created_after: str | Unset = UNSET
+ if not isinstance(created_after, Unset):
+ json_created_after = created_after.isoformat()
+ params["created_after"] = json_created_after
+
+ json_resource_type: str | Unset = UNSET
+ if not isinstance(resource_type, Unset):
+ json_resource_type = resource_type
+
+ params["resource_type"] = json_resource_type
+
+ json_status: str | Unset = UNSET
+ if not isinstance(status, Unset):
+ json_status = status
+
+ params["status"] = json_status
+
+ json_operation: str | Unset = UNSET
+ if not isinstance(operation, Unset):
+ json_operation = operation
+
+ params["operation"] = json_operation
+
+ json_order: str | Unset = UNSET
+ if not isinstance(order, Unset):
+ json_order = order
+
+ params["order"] = json_order
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/deployments",
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedProjectDeployments | None:
+ if response.status_code == 200:
+ response_200 = PaginatedProjectDeployments.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedProjectDeployments]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ owner_id: str | Unset = UNSET,
+ project_id: UUID | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListDeploymentsResourceType | Unset = UNSET,
+ status: ListDeploymentsStatus | Unset = UNSET,
+ operation: ListDeploymentsOperation | Unset = UNSET,
+ order: ListDeploymentsOrder | Unset = 'created_at.desc',
+
+) -> Response[Error | PaginatedProjectDeployments]:
+ r""" List deployments across a user's projects
+
+ Lists Function and Frontend deployment attempts across every project the
+ user owns, newest first. Pass `project_id` to narrow the feed to a single
+ project.
+
+ Scope is project **ownership** (`projects.user_id`). `owner_id` names
+ whose deployments to return, not who started them — the actor is
+ `initiated_by_user_id`, which this endpoint does not filter on.
+
+ With a user token the scope is always the authenticated user: `owner_id`
+ may be omitted, or set to that same user, but naming anyone else is
+ refused with 403. Service callers on the management API must pass it,
+ since they have no authenticated user.
+
+ The owner is not checked for existence: an id with no projects returns an
+ empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is
+ polled to detect an event, so a caller needs `404` to keep meaning \"this
+ route is not served here\" — which is how a consumer notices it is running
+ against an older release. A mistyped owner therefore reads as \"nothing
+ deployed\"; callers that need to tell those apart should verify the user
+ through `GET /users/{id}` first.
+
+ Ordering is selectable. The default is the feed order — most recent
+ attempt first. `completed_at.asc` orders by completion, oldest first, and
+ considers only attempts that finished; combined with `limit=1` and a
+ `status` filter it answers \"when did this user first succeed\" in one
+ bounded query.
+
+ Both pagination modes are supported, selected exactly as
+ `/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a
+ `limit` with no `page`) uses keyset pagination; otherwise `page`/`limit`
+ offset pagination. `page` with a cursor, and `cursor` with
+ `ending_before`, are rejected.
+
+ A cursor is bound to every filter *and* to `order`, so changing any of
+ them mid-pagination rejects the cursor rather than silently skipping or
+ repeating rows. The keyset position is `(created_at, id)` for
+ `created_at.desc` and `(completed_at, id)` for `completed_at.asc`.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ owner_id (str | Unset):
+ project_id (UUID | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListDeploymentsResourceType | Unset):
+ status (ListDeploymentsStatus | Unset):
+ operation (ListDeploymentsOperation | Unset):
+ order (ListDeploymentsOrder | Unset): Default: 'created_at.desc'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjectDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+owner_id=owner_id,
+project_id=project_id,
+created_after=created_after,
+resource_type=resource_type,
+status=status,
+operation=operation,
+order=order,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ owner_id: str | Unset = UNSET,
+ project_id: UUID | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListDeploymentsResourceType | Unset = UNSET,
+ status: ListDeploymentsStatus | Unset = UNSET,
+ operation: ListDeploymentsOperation | Unset = UNSET,
+ order: ListDeploymentsOrder | Unset = 'created_at.desc',
+
+) -> Error | PaginatedProjectDeployments | None:
+ r""" List deployments across a user's projects
+
+ Lists Function and Frontend deployment attempts across every project the
+ user owns, newest first. Pass `project_id` to narrow the feed to a single
+ project.
+
+ Scope is project **ownership** (`projects.user_id`). `owner_id` names
+ whose deployments to return, not who started them — the actor is
+ `initiated_by_user_id`, which this endpoint does not filter on.
+
+ With a user token the scope is always the authenticated user: `owner_id`
+ may be omitted, or set to that same user, but naming anyone else is
+ refused with 403. Service callers on the management API must pass it,
+ since they have no authenticated user.
+
+ The owner is not checked for existence: an id with no projects returns an
+ empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is
+ polled to detect an event, so a caller needs `404` to keep meaning \"this
+ route is not served here\" — which is how a consumer notices it is running
+ against an older release. A mistyped owner therefore reads as \"nothing
+ deployed\"; callers that need to tell those apart should verify the user
+ through `GET /users/{id}` first.
+
+ Ordering is selectable. The default is the feed order — most recent
+ attempt first. `completed_at.asc` orders by completion, oldest first, and
+ considers only attempts that finished; combined with `limit=1` and a
+ `status` filter it answers \"when did this user first succeed\" in one
+ bounded query.
+
+ Both pagination modes are supported, selected exactly as
+ `/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a
+ `limit` with no `page`) uses keyset pagination; otherwise `page`/`limit`
+ offset pagination. `page` with a cursor, and `cursor` with
+ `ending_before`, are rejected.
+
+ A cursor is bound to every filter *and* to `order`, so changing any of
+ them mid-pagination rejects the cursor rather than silently skipping or
+ repeating rows. The keyset position is `(created_at, id)` for
+ `created_at.desc` and `(completed_at, id)` for `completed_at.asc`.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ owner_id (str | Unset):
+ project_id (UUID | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListDeploymentsResourceType | Unset):
+ status (ListDeploymentsStatus | Unset):
+ operation (ListDeploymentsOperation | Unset):
+ order (ListDeploymentsOrder | Unset): Default: 'created_at.desc'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjectDeployments
+ """
+
+
+ return sync_detailed(
+ client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+owner_id=owner_id,
+project_id=project_id,
+created_after=created_after,
+resource_type=resource_type,
+status=status,
+operation=operation,
+order=order,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ owner_id: str | Unset = UNSET,
+ project_id: UUID | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListDeploymentsResourceType | Unset = UNSET,
+ status: ListDeploymentsStatus | Unset = UNSET,
+ operation: ListDeploymentsOperation | Unset = UNSET,
+ order: ListDeploymentsOrder | Unset = 'created_at.desc',
+
+) -> Response[Error | PaginatedProjectDeployments]:
+ r""" List deployments across a user's projects
+
+ Lists Function and Frontend deployment attempts across every project the
+ user owns, newest first. Pass `project_id` to narrow the feed to a single
+ project.
+
+ Scope is project **ownership** (`projects.user_id`). `owner_id` names
+ whose deployments to return, not who started them — the actor is
+ `initiated_by_user_id`, which this endpoint does not filter on.
+
+ With a user token the scope is always the authenticated user: `owner_id`
+ may be omitted, or set to that same user, but naming anyone else is
+ refused with 403. Service callers on the management API must pass it,
+ since they have no authenticated user.
+
+ The owner is not checked for existence: an id with no projects returns an
+ empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is
+ polled to detect an event, so a caller needs `404` to keep meaning \"this
+ route is not served here\" — which is how a consumer notices it is running
+ against an older release. A mistyped owner therefore reads as \"nothing
+ deployed\"; callers that need to tell those apart should verify the user
+ through `GET /users/{id}` first.
+
+ Ordering is selectable. The default is the feed order — most recent
+ attempt first. `completed_at.asc` orders by completion, oldest first, and
+ considers only attempts that finished; combined with `limit=1` and a
+ `status` filter it answers \"when did this user first succeed\" in one
+ bounded query.
+
+ Both pagination modes are supported, selected exactly as
+ `/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a
+ `limit` with no `page`) uses keyset pagination; otherwise `page`/`limit`
+ offset pagination. `page` with a cursor, and `cursor` with
+ `ending_before`, are rejected.
+
+ A cursor is bound to every filter *and* to `order`, so changing any of
+ them mid-pagination rejects the cursor rather than silently skipping or
+ repeating rows. The keyset position is `(created_at, id)` for
+ `created_at.desc` and `(completed_at, id)` for `completed_at.asc`.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ owner_id (str | Unset):
+ project_id (UUID | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListDeploymentsResourceType | Unset):
+ status (ListDeploymentsStatus | Unset):
+ operation (ListDeploymentsOperation | Unset):
+ order (ListDeploymentsOrder | Unset): Default: 'created_at.desc'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjectDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+owner_id=owner_id,
+project_id=project_id,
+created_after=created_after,
+resource_type=resource_type,
+status=status,
+operation=operation,
+order=order,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ owner_id: str | Unset = UNSET,
+ project_id: UUID | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListDeploymentsResourceType | Unset = UNSET,
+ status: ListDeploymentsStatus | Unset = UNSET,
+ operation: ListDeploymentsOperation | Unset = UNSET,
+ order: ListDeploymentsOrder | Unset = 'created_at.desc',
+
+) -> Error | PaginatedProjectDeployments | None:
+ r""" List deployments across a user's projects
+
+ Lists Function and Frontend deployment attempts across every project the
+ user owns, newest first. Pass `project_id` to narrow the feed to a single
+ project.
+
+ Scope is project **ownership** (`projects.user_id`). `owner_id` names
+ whose deployments to return, not who started them — the actor is
+ `initiated_by_user_id`, which this endpoint does not filter on.
+
+ With a user token the scope is always the authenticated user: `owner_id`
+ may be omitted, or set to that same user, but naming anyone else is
+ refused with 403. Service callers on the management API must pass it,
+ since they have no authenticated user.
+
+ The owner is not checked for existence: an id with no projects returns an
+ empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is
+ polled to detect an event, so a caller needs `404` to keep meaning \"this
+ route is not served here\" — which is how a consumer notices it is running
+ against an older release. A mistyped owner therefore reads as \"nothing
+ deployed\"; callers that need to tell those apart should verify the user
+ through `GET /users/{id}` first.
+
+ Ordering is selectable. The default is the feed order — most recent
+ attempt first. `completed_at.asc` orders by completion, oldest first, and
+ considers only attempts that finished; combined with `limit=1` and a
+ `status` filter it answers \"when did this user first succeed\" in one
+ bounded query.
+
+ Both pagination modes are supported, selected exactly as
+ `/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a
+ `limit` with no `page`) uses keyset pagination; otherwise `page`/`limit`
+ offset pagination. `page` with a cursor, and `cursor` with
+ `ending_before`, are rejected.
+
+ A cursor is bound to every filter *and* to `order`, so changing any of
+ them mid-pagination rejects the cursor rather than silently skipping or
+ repeating rows. The keyset position is `(created_at, id)` for
+ `created_at.desc` and `(completed_at, id)` for `completed_at.asc`.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ owner_id (str | Unset):
+ project_id (UUID | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListDeploymentsResourceType | Unset):
+ status (ListDeploymentsStatus | Unset):
+ operation (ListDeploymentsOperation | Unset):
+ order (ListDeploymentsOrder | Unset): Default: 'created_at.desc'.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjectDeployments
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+owner_id=owner_id,
+project_id=project_id,
+created_after=created_after,
+resource_type=resource_type,
+status=status,
+operation=operation,
+order=order,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/list_project_deployments.py b/src/volcano_sdk/_generated/api/projects/list_project_deployments.py
new file mode 100644
index 00000000..e72c5723
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/list_project_deployments.py
@@ -0,0 +1,358 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.list_project_deployments_resource_type import check_list_project_deployments_resource_type
+from ...models.list_project_deployments_resource_type import ListProjectDeploymentsResourceType
+from ...models.paginated_project_deployments import PaginatedProjectDeployments
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListProjectDeploymentsResourceType | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+ json_created_after: str | Unset = UNSET
+ if not isinstance(created_after, Unset):
+ json_created_after = created_after.isoformat()
+ params["created_after"] = json_created_after
+
+ json_resource_type: str | Unset = UNSET
+ if not isinstance(resource_type, Unset):
+ json_resource_type = resource_type
+
+ params["resource_type"] = json_resource_type
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/deployments".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedProjectDeployments | None:
+ if response.status_code == 200:
+ response_200 = PaginatedProjectDeployments.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedProjectDeployments]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListProjectDeploymentsResourceType | Unset = UNSET,
+
+) -> Response[Error | PaginatedProjectDeployments]:
+ """ List deployments in a project
+
+ Lists Function and Frontend deployment attempts across the project,
+ ordered most-recent first. Each item includes a normalized resource
+ reference so clients can render both resource types without extra
+ fetches.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListProjectDeploymentsResourceType | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjectDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+created_after=created_after,
+resource_type=resource_type,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListProjectDeploymentsResourceType | Unset = UNSET,
+
+) -> Error | PaginatedProjectDeployments | None:
+ """ List deployments in a project
+
+ Lists Function and Frontend deployment attempts across the project,
+ ordered most-recent first. Each item includes a normalized resource
+ reference so clients can render both resource types without extra
+ fetches.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListProjectDeploymentsResourceType | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjectDeployments
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+created_after=created_after,
+resource_type=resource_type,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListProjectDeploymentsResourceType | Unset = UNSET,
+
+) -> Response[Error | PaginatedProjectDeployments]:
+ """ List deployments in a project
+
+ Lists Function and Frontend deployment attempts across the project,
+ ordered most-recent first. Each item includes a normalized resource
+ reference so clients can render both resource types without extra
+ fetches.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListProjectDeploymentsResourceType | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjectDeployments]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+created_after=created_after,
+resource_type=resource_type,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+ created_after: datetime.datetime | Unset = UNSET,
+ resource_type: ListProjectDeploymentsResourceType | Unset = UNSET,
+
+) -> Error | PaginatedProjectDeployments | None:
+ """ List deployments in a project
+
+ Lists Function and Frontend deployment attempts across the project,
+ ordered most-recent first. Each item includes a normalized resource
+ reference so clients can render both resource types without extra
+ fetches.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+ created_after (datetime.datetime | Unset):
+ resource_type (ListProjectDeploymentsResourceType | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjectDeployments
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+created_after=created_after,
+resource_type=resource_type,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/list_projects.py b/src/volcano_sdk/_generated/api/projects/list_projects.py
new file mode 100644
index 00000000..33ff9e47
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/list_projects.py
@@ -0,0 +1,299 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.paginated_projects import PaginatedProjects
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects",
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedProjects | None:
+ if response.status_code == 200:
+ response_200 = PaginatedProjects.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedProjects]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedProjects]:
+ """ List all projects for authenticated user
+
+ Returns projects that are not deleting or deleted, newest first.
+ Supports two mutually exclusive pagination modes. Offset mode uses
+ `page` and `limit`. Cursor mode uses `cursor` or `ending_before` with
+ `limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded
+ `offset` past the cursor anchor. Supplying `limit` without `page`
+ selects cursor mode. `search` applies a case-insensitive project-name
+ filter in either mode. Sending `page` with `cursor` or `ending_before`,
+ or sending both cursor directions, returns 400.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjects]
+ """
+
+
+ kwargs = _get_kwargs(
+ page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedProjects | None:
+ """ List all projects for authenticated user
+
+ Returns projects that are not deleting or deleted, newest first.
+ Supports two mutually exclusive pagination modes. Offset mode uses
+ `page` and `limit`. Cursor mode uses `cursor` or `ending_before` with
+ `limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded
+ `offset` past the cursor anchor. Supplying `limit` without `page`
+ selects cursor mode. `search` applies a case-insensitive project-name
+ filter in either mode. Sending `page` with `cursor` or `ending_before`,
+ or sending both cursor directions, returns 400.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjects
+ """
+
+
+ return sync_detailed(
+ client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedProjects]:
+ """ List all projects for authenticated user
+
+ Returns projects that are not deleting or deleted, newest first.
+ Supports two mutually exclusive pagination modes. Offset mode uses
+ `page` and `limit`. Cursor mode uses `cursor` or `ending_before` with
+ `limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded
+ `offset` past the cursor anchor. Supplying `limit` without `page`
+ selects cursor mode. `search` applies a case-insensitive project-name
+ filter in either mode. Sending `page` with `cursor` or `ending_before`,
+ or sending both cursor directions, returns 400.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedProjects]
+ """
+
+
+ kwargs = _get_kwargs(
+ page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedProjects | None:
+ """ List all projects for authenticated user
+
+ Returns projects that are not deleting or deleted, newest first.
+ Supports two mutually exclusive pagination modes. Offset mode uses
+ `page` and `limit`. Cursor mode uses `cursor` or `ending_before` with
+ `limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded
+ `offset` past the cursor anchor. Supplying `limit` without `page`
+ selects cursor mode. `search` applies a case-insensitive project-name
+ filter in either mode. Sending `page` with `cursor` or `ending_before`,
+ or sending both cursor directions, returns 400.
+
+ Args:
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedProjects
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/query_project_metrics.py b/src/volcano_sdk/_generated/api/projects/query_project_metrics.py
new file mode 100644
index 00000000..0c117248
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/query_project_metrics.py
@@ -0,0 +1,251 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_metrics_query_request import ProjectMetricsQueryRequest
+from ...models.project_metrics_query_response import ProjectMetricsQueryResponse
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: ProjectMetricsQueryRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/metrics/query".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectMetricsQueryResponse | None:
+ if response.status_code == 200:
+ response_200 = ProjectMetricsQueryResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectMetricsQueryResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectMetricsQueryRequest,
+
+) -> Response[Error | ProjectMetricsQueryResponse]:
+ """ Query project runtime metrics
+
+ Evaluates a batch of named, curated runtime metric queries over one
+ trailing time range. Query IDs correlate each request with its result;
+ raw backend query languages are intentionally not exposed.
+
+ Args:
+ id (UUID):
+ body (ProjectMetricsQueryRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectMetricsQueryResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectMetricsQueryRequest,
+
+) -> Error | ProjectMetricsQueryResponse | None:
+ """ Query project runtime metrics
+
+ Evaluates a batch of named, curated runtime metric queries over one
+ trailing time range. Query IDs correlate each request with its result;
+ raw backend query languages are intentionally not exposed.
+
+ Args:
+ id (UUID):
+ body (ProjectMetricsQueryRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectMetricsQueryResponse
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectMetricsQueryRequest,
+
+) -> Response[Error | ProjectMetricsQueryResponse]:
+ """ Query project runtime metrics
+
+ Evaluates a batch of named, curated runtime metric queries over one
+ trailing time range. Query IDs correlate each request with its result;
+ raw backend query languages are intentionally not exposed.
+
+ Args:
+ id (UUID):
+ body (ProjectMetricsQueryRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectMetricsQueryResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: ProjectMetricsQueryRequest,
+
+) -> Error | ProjectMetricsQueryResponse | None:
+ """ Query project runtime metrics
+
+ Evaluates a batch of named, curated runtime metric queries over one
+ trailing time range. Query IDs correlate each request with its result;
+ raw backend query languages are intentionally not exposed.
+
+ Args:
+ id (UUID):
+ body (ProjectMetricsQueryRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectMetricsQueryResponse
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/set_project_git_production_branch.py b/src/volcano_sdk/_generated/api/projects/set_project_git_production_branch.py
new file mode 100644
index 00000000..3975a49d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/set_project_git_production_branch.py
@@ -0,0 +1,284 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_git_connection import ProjectGitConnection
+from ...models.set_project_git_production_branch_request import SetProjectGitProductionBranchRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: SetProjectGitProductionBranchRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/git-connection/production-branch".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectGitConnection | None:
+ if response.status_code == 200:
+ response_200 = ProjectGitConnection.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectGitConnection]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: SetProjectGitProductionBranchRequest,
+
+) -> Response[Error | ProjectGitConnection]:
+ """ Set the branch a project deploys from
+
+ Changes only the production branch, leaving the repository binding
+ alone. PUT /projects/{id}/git-connection can also set it, but that is a
+ full rebind: it needs connection_id, installation_id and a repository
+ selector resent, and re-resolves the repository against GitHub for a
+ field that does not depend on it.
+
+ The branch does not have to exist. It is validated as a Git branch name
+ and nothing more, so a project can be pointed at a branch that is about
+ to be pushed — the case a repository created empty depends on.
+
+ Setting the branch here marks it as the project's own choice, so a later
+ default-branch rename on GitHub no longer moves it. Projects that never
+ set one keep following the repository's default branch.
+
+ Args:
+ id (UUID):
+ body (SetProjectGitProductionBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitConnection]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: SetProjectGitProductionBranchRequest,
+
+) -> Error | ProjectGitConnection | None:
+ """ Set the branch a project deploys from
+
+ Changes only the production branch, leaving the repository binding
+ alone. PUT /projects/{id}/git-connection can also set it, but that is a
+ full rebind: it needs connection_id, installation_id and a repository
+ selector resent, and re-resolves the repository against GitHub for a
+ field that does not depend on it.
+
+ The branch does not have to exist. It is validated as a Git branch name
+ and nothing more, so a project can be pointed at a branch that is about
+ to be pushed — the case a repository created empty depends on.
+
+ Setting the branch here marks it as the project's own choice, so a later
+ default-branch rename on GitHub no longer moves it. Projects that never
+ set one keep following the repository's default branch.
+
+ Args:
+ id (UUID):
+ body (SetProjectGitProductionBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitConnection
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: SetProjectGitProductionBranchRequest,
+
+) -> Response[Error | ProjectGitConnection]:
+ """ Set the branch a project deploys from
+
+ Changes only the production branch, leaving the repository binding
+ alone. PUT /projects/{id}/git-connection can also set it, but that is a
+ full rebind: it needs connection_id, installation_id and a repository
+ selector resent, and re-resolves the repository against GitHub for a
+ field that does not depend on it.
+
+ The branch does not have to exist. It is validated as a Git branch name
+ and nothing more, so a project can be pointed at a branch that is about
+ to be pushed — the case a repository created empty depends on.
+
+ Setting the branch here marks it as the project's own choice, so a later
+ default-branch rename on GitHub no longer moves it. Projects that never
+ set one keep following the repository's default branch.
+
+ Args:
+ id (UUID):
+ body (SetProjectGitProductionBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitConnection]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: SetProjectGitProductionBranchRequest,
+
+) -> Error | ProjectGitConnection | None:
+ """ Set the branch a project deploys from
+
+ Changes only the production branch, leaving the repository binding
+ alone. PUT /projects/{id}/git-connection can also set it, but that is a
+ full rebind: it needs connection_id, installation_id and a repository
+ selector resent, and re-resolves the repository against GitHub for a
+ field that does not depend on it.
+
+ The branch does not have to exist. It is validated as a Git branch name
+ and nothing more, so a project can be pointed at a branch that is about
+ to be pushed — the case a repository created empty depends on.
+
+ Setting the branch here marks it as the project's own choice, so a later
+ default-branch rename on GitHub no longer moves it. Projects that never
+ set one keep following the repository's default branch.
+
+ Args:
+ id (UUID):
+ body (SetProjectGitProductionBranchRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitConnection
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/summarize_project_deployments.py b/src/volcano_sdk/_generated/api/projects/summarize_project_deployments.py
new file mode 100644
index 00000000..22c4268f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/summarize_project_deployments.py
@@ -0,0 +1,288 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_deployment_summary import ProjectDeploymentSummary
+from ...models.summarize_project_deployments_resource_type import check_summarize_project_deployments_resource_type
+from ...models.summarize_project_deployments_resource_type import SummarizeProjectDeploymentsResourceType
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ search: str | Unset = UNSET,
+ resource_type: SummarizeProjectDeploymentsResourceType,
+ created_after: datetime.datetime | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["search"] = search
+
+ json_resource_type: str = resource_type
+ params["resource_type"] = json_resource_type
+
+ json_created_after: str | Unset = UNSET
+ if not isinstance(created_after, Unset):
+ json_created_after = created_after.isoformat()
+ params["created_after"] = json_created_after
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/deployments/summary".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectDeploymentSummary | None:
+ if response.status_code == 200:
+ response_200 = ProjectDeploymentSummary.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectDeploymentSummary]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ search: str | Unset = UNSET,
+ resource_type: SummarizeProjectDeploymentsResourceType,
+ created_after: datetime.datetime | Unset = UNSET,
+
+) -> Response[Error | ProjectDeploymentSummary]:
+ """ Summarize deployments in a project
+
+ Summarizes deployment attempts for one comparable resource pipeline.
+ Success rate uses conclusive outcomes only: active and deleted attempts
+ are successful; failed and degraded attempts are failures; in-progress
+ and superseded attempts are excluded. Median build duration includes
+ completed, non-superseded attempts with recorded build work,
+ including failed builds.
+
+ Args:
+ id (UUID):
+ search (str | Unset):
+ resource_type (SummarizeProjectDeploymentsResourceType):
+ created_after (datetime.datetime | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectDeploymentSummary]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+search=search,
+resource_type=resource_type,
+created_after=created_after,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ search: str | Unset = UNSET,
+ resource_type: SummarizeProjectDeploymentsResourceType,
+ created_after: datetime.datetime | Unset = UNSET,
+
+) -> Error | ProjectDeploymentSummary | None:
+ """ Summarize deployments in a project
+
+ Summarizes deployment attempts for one comparable resource pipeline.
+ Success rate uses conclusive outcomes only: active and deleted attempts
+ are successful; failed and degraded attempts are failures; in-progress
+ and superseded attempts are excluded. Median build duration includes
+ completed, non-superseded attempts with recorded build work,
+ including failed builds.
+
+ Args:
+ id (UUID):
+ search (str | Unset):
+ resource_type (SummarizeProjectDeploymentsResourceType):
+ created_after (datetime.datetime | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectDeploymentSummary
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+search=search,
+resource_type=resource_type,
+created_after=created_after,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ search: str | Unset = UNSET,
+ resource_type: SummarizeProjectDeploymentsResourceType,
+ created_after: datetime.datetime | Unset = UNSET,
+
+) -> Response[Error | ProjectDeploymentSummary]:
+ """ Summarize deployments in a project
+
+ Summarizes deployment attempts for one comparable resource pipeline.
+ Success rate uses conclusive outcomes only: active and deleted attempts
+ are successful; failed and degraded attempts are failures; in-progress
+ and superseded attempts are excluded. Median build duration includes
+ completed, non-superseded attempts with recorded build work,
+ including failed builds.
+
+ Args:
+ id (UUID):
+ search (str | Unset):
+ resource_type (SummarizeProjectDeploymentsResourceType):
+ created_after (datetime.datetime | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectDeploymentSummary]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+search=search,
+resource_type=resource_type,
+created_after=created_after,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ search: str | Unset = UNSET,
+ resource_type: SummarizeProjectDeploymentsResourceType,
+ created_after: datetime.datetime | Unset = UNSET,
+
+) -> Error | ProjectDeploymentSummary | None:
+ """ Summarize deployments in a project
+
+ Summarizes deployment attempts for one comparable resource pipeline.
+ Success rate uses conclusive outcomes only: active and deleted attempts
+ are successful; failed and degraded attempts are failures; in-progress
+ and superseded attempts are excluded. Median build duration includes
+ completed, non-superseded attempts with recorded build work,
+ including failed builds.
+
+ Args:
+ id (UUID):
+ search (str | Unset):
+ resource_type (SummarizeProjectDeploymentsResourceType):
+ created_after (datetime.datetime | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectDeploymentSummary
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+search=search,
+resource_type=resource_type,
+created_after=created_after,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/update_project.py b/src/volcano_sdk/_generated/api/projects/update_project.py
new file mode 100644
index 00000000..d43e816a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/update_project.py
@@ -0,0 +1,221 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project import Project
+from ...models.update_project_request import UpdateProjectRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: UpdateProjectRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/projects/{id}".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Project | None:
+ if response.status_code == 200:
+ response_200 = Project.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Project]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectRequest,
+
+) -> Response[Error | Project]:
+ """ Update project metadata and region policy
+
+ Args:
+ id (UUID):
+ body (UpdateProjectRequest): Update mutable project fields (name and/or region policy)
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectRequest,
+
+) -> Error | Project | None:
+ """ Update project metadata and region policy
+
+ Args:
+ id (UUID):
+ body (UpdateProjectRequest): Update mutable project fields (name and/or region policy)
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectRequest,
+
+) -> Response[Error | Project]:
+ """ Update project metadata and region policy
+
+ Args:
+ id (UUID):
+ body (UpdateProjectRequest): Update mutable project fields (name and/or region policy)
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectRequest,
+
+) -> Error | Project | None:
+ """ Update project metadata and region policy
+
+ Args:
+ id (UUID):
+ body (UpdateProjectRequest): Update mutable project fields (name and/or region policy)
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/update_project_git_deploy_settings.py b/src/volcano_sdk/_generated/api/projects/update_project_git_deploy_settings.py
new file mode 100644
index 00000000..a661379a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/update_project_git_deploy_settings.py
@@ -0,0 +1,280 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project_git_deploy_settings import ProjectGitDeploySettings
+from ...models.update_project_git_deploy_settings_request import UpdateProjectGitDeploySettingsRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: UpdateProjectGitDeploySettingsRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/git-deploy-settings".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | ProjectGitDeploySettings | None:
+ if response.status_code == 200:
+ response_200 = ProjectGitDeploySettings.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 500:
+ response_500 = Error.from_dict(response.json())
+
+
+
+ return response_500
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | ProjectGitDeploySettings]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectGitDeploySettingsRequest,
+
+) -> Response[Error | ProjectGitDeploySettings]:
+ """ Update a project's Git auto-deploy settings
+
+ Full replace of the project's Git auto-deploy settings: what a push to
+ the connected repo's production branch deploys.
+
+ Connecting a repository sets auto_deploy_enabled and deploy_functions
+ to true for a project that has never called this endpoint, so a push
+ deploys without any further setup. Once these settings have been saved
+ here they are the project's own: connecting, rebinding, disconnecting
+ and reconnecting all leave them untouched, including when they were
+ saved before any repository was connected. Frontend settings are off
+ until set here; the frontend need not exist when they are saved, since
+ frontend_name is resolved at deploy time.
+
+ Args:
+ id (UUID):
+ body (UpdateProjectGitDeploySettingsRequest): Full replace of a project's Git auto-deploy
+ settings.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitDeploySettings]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectGitDeploySettingsRequest,
+
+) -> Error | ProjectGitDeploySettings | None:
+ """ Update a project's Git auto-deploy settings
+
+ Full replace of the project's Git auto-deploy settings: what a push to
+ the connected repo's production branch deploys.
+
+ Connecting a repository sets auto_deploy_enabled and deploy_functions
+ to true for a project that has never called this endpoint, so a push
+ deploys without any further setup. Once these settings have been saved
+ here they are the project's own: connecting, rebinding, disconnecting
+ and reconnecting all leave them untouched, including when they were
+ saved before any repository was connected. Frontend settings are off
+ until set here; the frontend need not exist when they are saved, since
+ frontend_name is resolved at deploy time.
+
+ Args:
+ id (UUID):
+ body (UpdateProjectGitDeploySettingsRequest): Full replace of a project's Git auto-deploy
+ settings.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitDeploySettings
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectGitDeploySettingsRequest,
+
+) -> Response[Error | ProjectGitDeploySettings]:
+ """ Update a project's Git auto-deploy settings
+
+ Full replace of the project's Git auto-deploy settings: what a push to
+ the connected repo's production branch deploys.
+
+ Connecting a repository sets auto_deploy_enabled and deploy_functions
+ to true for a project that has never called this endpoint, so a push
+ deploys without any further setup. Once these settings have been saved
+ here they are the project's own: connecting, rebinding, disconnecting
+ and reconnecting all leave them untouched, including when they were
+ saved before any repository was connected. Frontend settings are off
+ until set here; the frontend need not exist when they are saved, since
+ frontend_name is resolved at deploy time.
+
+ Args:
+ id (UUID):
+ body (UpdateProjectGitDeploySettingsRequest): Full replace of a project's Git auto-deploy
+ settings.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | ProjectGitDeploySettings]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateProjectGitDeploySettingsRequest,
+
+) -> Error | ProjectGitDeploySettings | None:
+ """ Update a project's Git auto-deploy settings
+
+ Full replace of the project's Git auto-deploy settings: what a push to
+ the connected repo's production branch deploys.
+
+ Connecting a repository sets auto_deploy_enabled and deploy_functions
+ to true for a project that has never called this endpoint, so a push
+ deploys without any further setup. Once these settings have been saved
+ here they are the project's own: connecting, rebinding, disconnecting
+ and reconnecting all leave them untouched, including when they were
+ saved before any repository was connected. Frontend settings are off
+ until set here; the frontend need not exist when they are saved, since
+ frontend_name is resolved at deploy time.
+
+ Args:
+ id (UUID):
+ body (UpdateProjectGitDeploySettingsRequest): Full replace of a project's Git auto-deploy
+ settings.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | ProjectGitDeploySettings
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/projects/upload_project_logo.py b/src/volcano_sdk/_generated/api/projects/upload_project_logo.py
new file mode 100644
index 00000000..416b6ccf
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/projects/upload_project_logo.py
@@ -0,0 +1,248 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.project import Project
+from ...models.upload_project_logo_body import UploadProjectLogoBody
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: UploadProjectLogoBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/logo".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["files"] = body.to_multipart()
+
+ headers["Content-Type"] = "multipart/form-data; boundary=+++"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Project | None:
+ if response.status_code == 200:
+ response_200 = Project.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = Error.from_dict(response.json())
+
+
+
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if response.status_code == 409:
+ response_409 = Error.from_dict(response.json())
+
+
+
+ return response_409
+
+ if response.status_code == 503:
+ response_503 = Error.from_dict(response.json())
+
+
+
+ return response_503
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Project]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UploadProjectLogoBody,
+
+) -> Response[Error | Project]:
+ """ Upload or replace the project logo
+
+ Uploads an image as the project's logo, storing it in the project's
+ storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any
+ existing logo. Returns the updated project, whose `logo_url` reflects
+ the new logo.
+
+ Args:
+ id (UUID):
+ body (UploadProjectLogoBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UploadProjectLogoBody,
+
+) -> Error | Project | None:
+ """ Upload or replace the project logo
+
+ Uploads an image as the project's logo, storing it in the project's
+ storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any
+ existing logo. Returns the updated project, whose `logo_url` reflects
+ the new logo.
+
+ Args:
+ id (UUID):
+ body (UploadProjectLogoBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UploadProjectLogoBody,
+
+) -> Response[Error | Project]:
+ """ Upload or replace the project logo
+
+ Uploads an image as the project's logo, storing it in the project's
+ storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any
+ existing logo. Returns the updated project, whose `logo_url` reflects
+ the new logo.
+
+ Args:
+ id (UUID):
+ body (UploadProjectLogoBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Project]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UploadProjectLogoBody,
+
+) -> Error | Project | None:
+ """ Upload or replace the project logo
+
+ Uploads an image as the project's logo, storing it in the project's
+ storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any
+ existing logo. Returns the updated project, whose `logo_url` reflects
+ the new logo.
+
+ Args:
+ id (UUID):
+ body (UploadProjectLogoBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Project
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/realtime/__init__.py b/src/volcano_sdk/_generated/api/realtime/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/realtime/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/realtime/get_realtime_config.py b/src/volcano_sdk/_generated/api/realtime/get_realtime_config.py
new file mode 100644
index 00000000..4cb70c04
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/realtime/get_realtime_config.py
@@ -0,0 +1,195 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.realtime_config import RealtimeConfig
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/realtime/config".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | RealtimeConfig | None:
+ if response.status_code == 200:
+ response_200 = RealtimeConfig.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | RealtimeConfig]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | RealtimeConfig]:
+ """ Get realtime configuration for a project
+
+ Returns the realtime configuration including enabled features and limits.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RealtimeConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | RealtimeConfig | None:
+ """ Get realtime configuration for a project
+
+ Returns the realtime configuration including enabled features and limits.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RealtimeConfig
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | RealtimeConfig]:
+ """ Get realtime configuration for a project
+
+ Returns the realtime configuration including enabled features and limits.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RealtimeConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | RealtimeConfig | None:
+ """ Get realtime configuration for a project
+
+ Returns the realtime configuration including enabled features and limits.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RealtimeConfig
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/realtime/get_realtime_stats.py b/src/volcano_sdk/_generated/api/realtime/get_realtime_stats.py
new file mode 100644
index 00000000..8d83c20f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/realtime/get_realtime_stats.py
@@ -0,0 +1,188 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.realtime_stats import RealtimeStats
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/realtime/stats".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | RealtimeStats | None:
+ if response.status_code == 200:
+ response_200 = RealtimeStats.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | RealtimeStats]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | RealtimeStats]:
+ """ Get realtime statistics for a project
+
+ Returns realtime usage statistics including connection counts and subscribed tables.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RealtimeStats]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | RealtimeStats | None:
+ """ Get realtime statistics for a project
+
+ Returns realtime usage statistics including connection counts and subscribed tables.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RealtimeStats
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | RealtimeStats]:
+ """ Get realtime statistics for a project
+
+ Returns realtime usage statistics including connection counts and subscribed tables.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RealtimeStats]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | RealtimeStats | None:
+ """ Get realtime statistics for a project
+
+ Returns realtime usage statistics including connection counts and subscribed tables.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RealtimeStats
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/realtime/update_realtime_config.py b/src/volcano_sdk/_generated/api/realtime/update_realtime_config.py
new file mode 100644
index 00000000..e515ca1e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/realtime/update_realtime_config.py
@@ -0,0 +1,219 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.realtime_config import RealtimeConfig
+from ...models.update_realtime_config_request import UpdateRealtimeConfigRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: UpdateRealtimeConfigRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/realtime/config".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | RealtimeConfig | None:
+ if response.status_code == 200:
+ response_200 = RealtimeConfig.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if response.status_code == 401:
+ response_401 = Error.from_dict(response.json())
+
+
+
+ return response_401
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | RealtimeConfig]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateRealtimeConfigRequest,
+
+) -> Response[Error | RealtimeConfig]:
+ """ Update realtime configuration for a project
+
+ Updates realtime settings including feature toggles and limits.
+
+ Args:
+ id (UUID):
+ body (UpdateRealtimeConfigRequest): Request to update realtime configuration.
+ Limits (message size, channels per connection) are plan-based and cannot be configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RealtimeConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateRealtimeConfigRequest,
+
+) -> Error | RealtimeConfig | None:
+ """ Update realtime configuration for a project
+
+ Updates realtime settings including feature toggles and limits.
+
+ Args:
+ id (UUID):
+ body (UpdateRealtimeConfigRequest): Request to update realtime configuration.
+ Limits (message size, channels per connection) are plan-based and cannot be configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RealtimeConfig
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateRealtimeConfigRequest,
+
+) -> Response[Error | RealtimeConfig]:
+ """ Update realtime configuration for a project
+
+ Updates realtime settings including feature toggles and limits.
+
+ Args:
+ id (UUID):
+ body (UpdateRealtimeConfigRequest): Request to update realtime configuration.
+ Limits (message size, channels per connection) are plan-based and cannot be configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | RealtimeConfig]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateRealtimeConfigRequest,
+
+) -> Error | RealtimeConfig | None:
+ """ Update realtime configuration for a project
+
+ Updates realtime settings including feature toggles and limits.
+
+ Args:
+ id (UUID):
+ body (UpdateRealtimeConfigRequest): Request to update realtime configuration.
+ Limits (message size, channels per connection) are plan-based and cannot be configured.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | RealtimeConfig
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/service_keys/__init__.py b/src/volcano_sdk/_generated/api/service_keys/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/service_keys/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/service_keys/create_service_key.py b/src/volcano_sdk/_generated/api/service_keys/create_service_key.py
new file mode 100644
index 00000000..f27b1c7a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/service_keys/create_service_key.py
@@ -0,0 +1,216 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_service_key_body import CreateServiceKeyBody
+from ...models.service_key import ServiceKey
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateServiceKeyBody,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/service-keys".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | ServiceKey | None:
+ if response.status_code == 201:
+ response_201 = ServiceKey.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 409:
+ response_409 = cast(Any, None)
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | ServiceKey]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateServiceKeyBody,
+
+) -> Response[Any | ServiceKey]:
+ """ Create service key
+
+ Create a new service role key for admin operations.
+
+ **WARNING:** Service keys bypass all RLS policies!
+ Store securely and NEVER expose in frontend code.
+
+ Args:
+ id (UUID):
+ body (CreateServiceKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | ServiceKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateServiceKeyBody,
+
+) -> Any | ServiceKey | None:
+ """ Create service key
+
+ Create a new service role key for admin operations.
+
+ **WARNING:** Service keys bypass all RLS policies!
+ Store securely and NEVER expose in frontend code.
+
+ Args:
+ id (UUID):
+ body (CreateServiceKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | ServiceKey
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateServiceKeyBody,
+
+) -> Response[Any | ServiceKey]:
+ """ Create service key
+
+ Create a new service role key for admin operations.
+
+ **WARNING:** Service keys bypass all RLS policies!
+ Store securely and NEVER expose in frontend code.
+
+ Args:
+ id (UUID):
+ body (CreateServiceKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | ServiceKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateServiceKeyBody,
+
+) -> Any | ServiceKey | None:
+ """ Create service key
+
+ Create a new service role key for admin operations.
+
+ **WARNING:** Service keys bypass all RLS policies!
+ Store securely and NEVER expose in frontend code.
+
+ Args:
+ id (UUID):
+ body (CreateServiceKeyBody):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | ServiceKey
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/service_keys/delete_service_key.py b/src/volcano_sdk/_generated/api/service_keys/delete_service_key.py
new file mode 100644
index 00000000..e24ca2fa
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/service_keys/delete_service_key.py
@@ -0,0 +1,129 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ key_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/service-keys/{key_id}".format(id=quote(str(id), safe=""),key_id=quote(str(key_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 204:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete service key
+
+ Permanently delete a service key.
+ Any services using this key will immediately lose access.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete service key
+
+ Permanently delete a service key.
+ Any services using this key will immediately lose access.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/service_keys/get_service_key.py b/src/volcano_sdk/_generated/api/service_keys/get_service_key.py
new file mode 100644
index 00000000..ad73c49e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/service_keys/get_service_key.py
@@ -0,0 +1,197 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.service_key import ServiceKey
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ key_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/service-keys/{key_id}".format(id=quote(str(id), safe=""),key_id=quote(str(key_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | ServiceKey | None:
+ if response.status_code == 200:
+ response_200 = ServiceKey.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | ServiceKey]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | ServiceKey]:
+ """ Get service key
+
+ Get details of a specific service key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | ServiceKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | ServiceKey | None:
+ """ Get service key
+
+ Get details of a specific service key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | ServiceKey
+ """
+
+
+ return sync_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | ServiceKey]:
+ """ Get service key
+
+ Get details of a specific service key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | ServiceKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | ServiceKey | None:
+ """ Get service key
+
+ Get details of a specific service key
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | ServiceKey
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/service_keys/list_service_keys.py b/src/volcano_sdk/_generated/api/service_keys/list_service_keys.py
new file mode 100644
index 00000000..01aaac64
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/service_keys/list_service_keys.py
@@ -0,0 +1,285 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.paginated_service_keys import PaginatedServiceKeys
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/service-keys".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> PaginatedServiceKeys | None:
+ if response.status_code == 200:
+ response_200 = PaginatedServiceKeys.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[PaginatedServiceKeys]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[PaginatedServiceKeys]:
+ """ List service keys (paginated)
+
+ List all service role keys for a project with pagination.
+
+ **WARNING:** Service keys bypass RLS - for backend/admin use only!
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[PaginatedServiceKeys]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> PaginatedServiceKeys | None:
+ """ List service keys (paginated)
+
+ List all service role keys for a project with pagination.
+
+ **WARNING:** Service keys bypass RLS - for backend/admin use only!
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ PaginatedServiceKeys
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[PaginatedServiceKeys]:
+ """ List service keys (paginated)
+
+ List all service role keys for a project with pagination.
+
+ **WARNING:** Service keys bypass RLS - for backend/admin use only!
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[PaginatedServiceKeys]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> PaginatedServiceKeys | None:
+ """ List service keys (paginated)
+
+ List all service role keys for a project with pagination.
+
+ **WARNING:** Service keys bypass RLS - for backend/admin use only!
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ PaginatedServiceKeys
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/service_keys/regenerate_service_key.py b/src/volcano_sdk/_generated/api/service_keys/regenerate_service_key.py
new file mode 100644
index 00000000..648c5b33
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/service_keys/regenerate_service_key.py
@@ -0,0 +1,201 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.service_key import ServiceKey
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ key_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/service-keys/{key_id}/regenerate".format(id=quote(str(id), safe=""),key_id=quote(str(key_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ServiceKey | None:
+ if response.status_code == 200:
+ response_200 = ServiceKey.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ServiceKey]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ServiceKey]:
+ """ Regenerate service key
+
+ Generate new JWT value for existing key.
+ The old key is immediately invalidated.
+ Update your backend services with the new key before regenerating in production.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ServiceKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ServiceKey | None:
+ """ Regenerate service key
+
+ Generate new JWT value for existing key.
+ The old key is immediately invalidated.
+ Update your backend services with the new key before regenerating in production.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ServiceKey
+ """
+
+
+ return sync_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[ServiceKey]:
+ """ Regenerate service key
+
+ Generate new JWT value for existing key.
+ The old key is immediately invalidated.
+ Update your backend services with the new key before regenerating in production.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ServiceKey]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+key_id=key_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ key_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> ServiceKey | None:
+ """ Regenerate service key
+
+ Generate new JWT value for existing key.
+ The old key is immediately invalidated.
+ Update your backend services with the new key before regenerating in production.
+
+ Args:
+ id (UUID):
+ key_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ServiceKey
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+key_id=key_id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_admin/__init__.py b/src/volcano_sdk/_generated/api/storage_admin/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_admin/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/storage_admin/get_storage_stats.py b/src/volcano_sdk/_generated/api/storage_admin/get_storage_stats.py
new file mode 100644
index 00000000..b4f8a188
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_admin/get_storage_stats.py
@@ -0,0 +1,180 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.storage_stats import StorageStats
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/storage/stats".format(id=quote(str(id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> StorageStats | None:
+ if response.status_code == 200:
+ response_200 = StorageStats.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[StorageStats]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[StorageStats]:
+ """ Get storage statistics for a project
+
+ Returns aggregate storage statistics including bucket count, object count, and total size.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[StorageStats]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> StorageStats | None:
+ """ Get storage statistics for a project
+
+ Returns aggregate storage statistics including bucket count, object count, and total size.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ StorageStats
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[StorageStats]:
+ """ Get storage statistics for a project
+
+ Returns aggregate storage statistics including bucket count, object count, and total size.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[StorageStats]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> StorageStats | None:
+ """ Get storage statistics for a project
+
+ Returns aggregate storage statistics including bucket count, object count, and total size.
+
+ Args:
+ id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ StorageStats
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_admin/list_storage_objects_admin.py b/src/volcano_sdk/_generated/api/storage_admin/list_storage_objects_admin.py
new file mode 100644
index 00000000..e4548f3d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_admin/list_storage_objects_admin.py
@@ -0,0 +1,299 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.list_storage_objects_admin_response_200 import ListStorageObjectsAdminResponse200
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ owner_id: UUID | Unset = UNSET,
+ page: int | Unset = 1,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ json_owner_id: str | Unset = UNSET
+ if not isinstance(owner_id, Unset):
+ json_owner_id = str(owner_id)
+ params["owner_id"] = json_owner_id
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/storage/objects".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> ListStorageObjectsAdminResponse200 | None:
+ if response.status_code == 200:
+ response_200 = ListStorageObjectsAdminResponse200.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[ListStorageObjectsAdminResponse200]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ owner_id: UUID | Unset = UNSET,
+ page: int | Unset = 1,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[ListStorageObjectsAdminResponse200]:
+ """ List all storage objects in a project
+
+ Returns a paginated list of all storage objects across all buckets in the project.
+ Supports filtering by owner and pagination.
+
+ Args:
+ id (UUID):
+ owner_id (UUID | Unset):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListStorageObjectsAdminResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+owner_id=owner_id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ owner_id: UUID | Unset = UNSET,
+ page: int | Unset = 1,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> ListStorageObjectsAdminResponse200 | None:
+ """ List all storage objects in a project
+
+ Returns a paginated list of all storage objects across all buckets in the project.
+ Supports filtering by owner and pagination.
+
+ Args:
+ id (UUID):
+ owner_id (UUID | Unset):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListStorageObjectsAdminResponse200
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+owner_id=owner_id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ owner_id: UUID | Unset = UNSET,
+ page: int | Unset = 1,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[ListStorageObjectsAdminResponse200]:
+ """ List all storage objects in a project
+
+ Returns a paginated list of all storage objects across all buckets in the project.
+ Supports filtering by owner and pagination.
+
+ Args:
+ id (UUID):
+ owner_id (UUID | Unset):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListStorageObjectsAdminResponse200]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+owner_id=owner_id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ owner_id: UUID | Unset = UNSET,
+ page: int | Unset = 1,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> ListStorageObjectsAdminResponse200 | None:
+ """ List all storage objects in a project
+
+ Returns a paginated list of all storage objects across all buckets in the project.
+ Supports filtering by owner and pagination.
+
+ Args:
+ id (UUID):
+ owner_id (UUID | Unset):
+ page (int | Unset): Default: 1.
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListStorageObjectsAdminResponse200
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+owner_id=owner_id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_buckets/__init__.py b/src/volcano_sdk/_generated/api/storage_buckets/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_buckets/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/storage_buckets/create_storage_bucket.py b/src/volcano_sdk/_generated/api/storage_buckets/create_storage_bucket.py
new file mode 100644
index 00000000..f6438415
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_buckets/create_storage_bucket.py
@@ -0,0 +1,196 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_storage_bucket_request import CreateStorageBucketRequest
+from ...models.storage_bucket import StorageBucket
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateStorageBucketRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/storage/buckets".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | StorageBucket | None:
+ if response.status_code == 201:
+ response_201 = StorageBucket.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 409:
+ response_409 = cast(Any, None)
+ return response_409
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | StorageBucket]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStorageBucketRequest,
+
+) -> Response[Any | StorageBucket]:
+ """ Create a new storage bucket
+
+ Args:
+ id (UUID):
+ body (CreateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | StorageBucket]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStorageBucketRequest,
+
+) -> Any | StorageBucket | None:
+ """ Create a new storage bucket
+
+ Args:
+ id (UUID):
+ body (CreateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | StorageBucket
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStorageBucketRequest,
+
+) -> Response[Any | StorageBucket]:
+ """ Create a new storage bucket
+
+ Args:
+ id (UUID):
+ body (CreateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | StorageBucket]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStorageBucketRequest,
+
+) -> Any | StorageBucket | None:
+ """ Create a new storage bucket
+
+ Args:
+ id (UUID):
+ body (CreateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | StorageBucket
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_buckets/delete_storage_bucket.py b/src/volcano_sdk/_generated/api/storage_buckets/delete_storage_bucket.py
new file mode 100644
index 00000000..60e3ff2e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_buckets/delete_storage_bucket.py
@@ -0,0 +1,123 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ bucket_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/storage/buckets/{bucket_name}".format(id=quote(str(id), safe=""),bucket_name=quote(str(bucket_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 200:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete storage bucket and all objects
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete storage bucket and all objects
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/storage_buckets/get_storage_bucket.py b/src/volcano_sdk/_generated/api/storage_buckets/get_storage_bucket.py
new file mode 100644
index 00000000..25b6a564
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_buckets/get_storage_bucket.py
@@ -0,0 +1,189 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.storage_bucket import StorageBucket
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ bucket_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/storage/buckets/{bucket_name}".format(id=quote(str(id), safe=""),bucket_name=quote(str(bucket_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | StorageBucket | None:
+ if response.status_code == 200:
+ response_200 = StorageBucket.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | StorageBucket]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | StorageBucket]:
+ """ Get storage bucket by name
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | StorageBucket]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | StorageBucket | None:
+ """ Get storage bucket by name
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | StorageBucket
+ """
+
+
+ return sync_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | StorageBucket]:
+ """ Get storage bucket by name
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | StorageBucket]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | StorageBucket | None:
+ """ Get storage bucket by name
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | StorageBucket
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_buckets/list_storage_buckets.py b/src/volcano_sdk/_generated/api/storage_buckets/list_storage_buckets.py
new file mode 100644
index 00000000..e9820b73
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_buckets/list_storage_buckets.py
@@ -0,0 +1,297 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.paginated_storage_buckets import PaginatedStorageBuckets
+from ...models.storage_bucket import StorageBucket
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/storage/buckets".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> list[StorageBucket] | PaginatedStorageBuckets | None:
+ if response.status_code == 200:
+ def _parse_response_200(data: object) -> list[StorageBucket] | PaginatedStorageBuckets:
+ try:
+ if not isinstance(data, list):
+ raise TypeError()
+ response_200_type_0 = []
+ _response_200_type_0 = data
+ for response_200_type_0_item_data in (_response_200_type_0):
+ response_200_type_0_item = StorageBucket.from_dict(response_200_type_0_item_data)
+
+
+
+ response_200_type_0.append(response_200_type_0_item)
+
+ return response_200_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ response_200_type_1 = PaginatedStorageBuckets.from_dict(data)
+
+
+
+ return response_200_type_1
+
+ response_200 = _parse_response_200(response.json())
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[list[StorageBucket] | PaginatedStorageBuckets]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[list[StorageBucket] | PaginatedStorageBuckets]:
+ """ List all storage buckets in a project
+
+ With no pagination params, returns the full bucket list as a bare array
+ (legacy). Supplying `cursor`, `ending_before`, `search`, or `limit`
+ switches to keyset (cursor) pagination and returns a paginated envelope
+ with `next_cursor`/`prev_cursor` and a filtered `total`.
+
+ Args:
+ id (UUID):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[StorageBucket] | PaginatedStorageBuckets]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> list[StorageBucket] | PaginatedStorageBuckets | None:
+ """ List all storage buckets in a project
+
+ With no pagination params, returns the full bucket list as a bare array
+ (legacy). Supplying `cursor`, `ending_before`, `search`, or `limit`
+ switches to keyset (cursor) pagination and returns a paginated envelope
+ with `next_cursor`/`prev_cursor` and a filtered `total`.
+
+ Args:
+ id (UUID):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[StorageBucket] | PaginatedStorageBuckets
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[list[StorageBucket] | PaginatedStorageBuckets]:
+ """ List all storage buckets in a project
+
+ With no pagination params, returns the full bucket list as a bare array
+ (legacy). Supplying `cursor`, `ending_before`, `search`, or `limit`
+ switches to keyset (cursor) pagination and returns a paginated envelope
+ with `next_cursor`/`prev_cursor` and a filtered `total`.
+
+ Args:
+ id (UUID):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[StorageBucket] | PaginatedStorageBuckets]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> list[StorageBucket] | PaginatedStorageBuckets | None:
+ """ List all storage buckets in a project
+
+ With no pagination params, returns the full bucket list as a bare array
+ (legacy). Supplying `cursor`, `ending_before`, `search`, or `limit`
+ switches to keyset (cursor) pagination and returns a paginated envelope
+ with `next_cursor`/`prev_cursor` and a filtered `total`.
+
+ Args:
+ id (UUID):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[StorageBucket] | PaginatedStorageBuckets
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_buckets/update_storage_bucket.py b/src/volcano_sdk/_generated/api/storage_buckets/update_storage_bucket.py
new file mode 100644
index 00000000..38ee2065
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_buckets/update_storage_bucket.py
@@ -0,0 +1,205 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.storage_bucket import StorageBucket
+from ...models.update_storage_bucket_request import UpdateStorageBucketRequest
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ bucket_name: str,
+ *,
+ body: UpdateStorageBucketRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/projects/{id}/storage/buckets/{bucket_name}".format(id=quote(str(id), safe=""),bucket_name=quote(str(bucket_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> StorageBucket | None:
+ if response.status_code == 200:
+ response_200 = StorageBucket.from_dict(response.json())
+
+
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[StorageBucket]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateStorageBucketRequest,
+
+) -> Response[StorageBucket]:
+ """ Update storage bucket settings
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (UpdateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[StorageBucket]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateStorageBucketRequest,
+
+) -> StorageBucket | None:
+ """ Update storage bucket settings
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (UpdateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ StorageBucket
+ """
+
+
+ return sync_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateStorageBucketRequest,
+
+) -> Response[StorageBucket]:
+ """ Update storage bucket settings
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (UpdateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[StorageBucket]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateStorageBucketRequest,
+
+) -> StorageBucket | None:
+ """ Update storage bucket settings
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (UpdateStorageBucketRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ StorageBucket
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/__init__.py b/src/volcano_sdk/_generated/api/storage_objects/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/storage_objects/copy_storage_object.py b/src/volcano_sdk/_generated/api/storage_objects/copy_storage_object.py
new file mode 100644
index 00000000..be7e5cc6
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/copy_storage_object.py
@@ -0,0 +1,203 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.storage_copy_request import StorageCopyRequest
+from ...models.storage_object import StorageObject
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ *,
+ body: StorageCopyRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/storage/{bucket_name}/copy".format(bucket_name=quote(str(bucket_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | StorageObject | None:
+ if response.status_code == 201:
+ response_201 = StorageObject.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error | StorageObject]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageCopyRequest,
+
+) -> Response[Any | Error | StorageObject]:
+ """ Copy an object
+
+ Args:
+ bucket_name (str):
+ body (StorageCopyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | StorageObject]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageCopyRequest,
+
+) -> Any | Error | StorageObject | None:
+ """ Copy an object
+
+ Args:
+ bucket_name (str):
+ body (StorageCopyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | StorageObject
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageCopyRequest,
+
+) -> Response[Any | Error | StorageObject]:
+ """ Copy an object
+
+ Args:
+ bucket_name (str):
+ body (StorageCopyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | StorageObject]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageCopyRequest,
+
+) -> Any | Error | StorageObject | None:
+ """ Copy an object
+
+ Args:
+ bucket_name (str):
+ body (StorageCopyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | StorageObject
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/delete_storage_object.py b/src/volcano_sdk/_generated/api/storage_objects/delete_storage_object.py
new file mode 100644
index 00000000..04175153
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/delete_storage_object.py
@@ -0,0 +1,248 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ path: str,
+ *,
+ x_upload_session: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ if not isinstance(x_upload_session, Unset):
+ headers["X-Upload-Session"] = x_upload_session
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/storage/{bucket_name}/{path}".format(bucket_name=quote(str(bucket_name), safe=""),path=quote(str(path), safe=""),),
+ }
+
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 200:
+ response_200 = cast(Any, None)
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Response[Any | Error]:
+ """ Delete a file or abort upload session
+
+ Delete a file, or abort a resumable upload session.
+
+ **File Delete (default):**
+ Deletes the file at the specified path.
+
+ **Abort Session (with X-Upload-Session header):**
+ Aborts a resumable upload session and cleans up any uploaded parts.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+x_upload_session=x_upload_session,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Any | Error | None:
+ """ Delete a file or abort upload session
+
+ Delete a file, or abort a resumable upload session.
+
+ **File Delete (default):**
+ Deletes the file at the specified path.
+
+ **Abort Session (with X-Upload-Session header):**
+ Aborts a resumable upload session and cleans up any uploaded parts.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+x_upload_session=x_upload_session,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Response[Any | Error]:
+ """ Delete a file or abort upload session
+
+ Delete a file, or abort a resumable upload session.
+
+ **File Delete (default):**
+ Deletes the file at the specified path.
+
+ **Abort Session (with X-Upload-Session header):**
+ Aborts a resumable upload session and cleans up any uploaded parts.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+x_upload_session=x_upload_session,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Any | Error | None:
+ """ Delete a file or abort upload session
+
+ Delete a file, or abort a resumable upload session.
+
+ **File Delete (default):**
+ Deletes the file at the specified path.
+
+ **Abort Session (with X-Upload-Session header):**
+ Aborts a resumable upload session and cleans up any uploaded parts.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+x_upload_session=x_upload_session,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/download_public_file.py b/src/volcano_sdk/_generated/api/storage_objects/download_public_file.py
new file mode 100644
index 00000000..d7a57fbe
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/download_public_file.py
@@ -0,0 +1,302 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ project_id: UUID,
+ bucket_name: str,
+ path: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/public/{project_id}/{bucket_name}/{path}".format(project_id=quote(str(project_id), safe=""),bucket_name=quote(str(bucket_name), safe=""),path=quote(str(path), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 206:
+ response_206 = cast(Any, None)
+ return response_206
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ project_id: UUID,
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Any | Error]:
+ """ Download a public file (no authentication required)
+
+ Download a file that has been marked as public. This endpoint requires NO authentication.
+
+ **Access Requirements:**
+ - The file must have `is_public: true` set via the visibility endpoint
+ - Private files will return 403 Forbidden
+
+ **Use Cases:**
+ - Shareable public URLs for profile pictures, public documents, etc.
+ - Embedding public files on external websites
+ - Direct linking without requiring SDK or authentication
+
+ **URL Format:**
+ ```
+ GET /public/{projectId}/{bucketName}/{path}
+ ```
+
+ **Example:**
+ ```
+ https://api.volcano.dev/public/abc123/avatars/user-photo.jpg
+ ```
+
+ **CORS:**
+ This endpoint allows all origins since the file is already public.
+
+ Args:
+ project_id (UUID):
+ bucket_name (str):
+ path (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ project_id=project_id,
+bucket_name=bucket_name,
+path=path,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ project_id: UUID,
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Any | Error | None:
+ """ Download a public file (no authentication required)
+
+ Download a file that has been marked as public. This endpoint requires NO authentication.
+
+ **Access Requirements:**
+ - The file must have `is_public: true` set via the visibility endpoint
+ - Private files will return 403 Forbidden
+
+ **Use Cases:**
+ - Shareable public URLs for profile pictures, public documents, etc.
+ - Embedding public files on external websites
+ - Direct linking without requiring SDK or authentication
+
+ **URL Format:**
+ ```
+ GET /public/{projectId}/{bucketName}/{path}
+ ```
+
+ **Example:**
+ ```
+ https://api.volcano.dev/public/abc123/avatars/user-photo.jpg
+ ```
+
+ **CORS:**
+ This endpoint allows all origins since the file is already public.
+
+ Args:
+ project_id (UUID):
+ bucket_name (str):
+ path (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ project_id=project_id,
+bucket_name=bucket_name,
+path=path,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ project_id: UUID,
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[Any | Error]:
+ """ Download a public file (no authentication required)
+
+ Download a file that has been marked as public. This endpoint requires NO authentication.
+
+ **Access Requirements:**
+ - The file must have `is_public: true` set via the visibility endpoint
+ - Private files will return 403 Forbidden
+
+ **Use Cases:**
+ - Shareable public URLs for profile pictures, public documents, etc.
+ - Embedding public files on external websites
+ - Direct linking without requiring SDK or authentication
+
+ **URL Format:**
+ ```
+ GET /public/{projectId}/{bucketName}/{path}
+ ```
+
+ **Example:**
+ ```
+ https://api.volcano.dev/public/abc123/avatars/user-photo.jpg
+ ```
+
+ **CORS:**
+ This endpoint allows all origins since the file is already public.
+
+ Args:
+ project_id (UUID):
+ bucket_name (str):
+ path (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ project_id=project_id,
+bucket_name=bucket_name,
+path=path,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ project_id: UUID,
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Any | Error | None:
+ """ Download a public file (no authentication required)
+
+ Download a file that has been marked as public. This endpoint requires NO authentication.
+
+ **Access Requirements:**
+ - The file must have `is_public: true` set via the visibility endpoint
+ - Private files will return 403 Forbidden
+
+ **Use Cases:**
+ - Shareable public URLs for profile pictures, public documents, etc.
+ - Embedding public files on external websites
+ - Direct linking without requiring SDK or authentication
+
+ **URL Format:**
+ ```
+ GET /public/{projectId}/{bucketName}/{path}
+ ```
+
+ **Example:**
+ ```
+ https://api.volcano.dev/public/abc123/avatars/user-photo.jpg
+ ```
+
+ **CORS:**
+ This endpoint allows all origins since the file is already public.
+
+ Args:
+ project_id (UUID):
+ bucket_name (str):
+ path (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ project_id=project_id,
+bucket_name=bucket_name,
+path=path,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/download_storage_object.py b/src/volcano_sdk/_generated/api/storage_objects/download_storage_object.py
new file mode 100644
index 00000000..cd1ff186
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/download_storage_object.py
@@ -0,0 +1,279 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...types import File, FileTypes
+from ...types import UNSET, Unset
+from io import BytesIO
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ path: str,
+ *,
+ range_: str | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ if not isinstance(range_, Unset):
+ headers["Range"] = range_
+
+ if not isinstance(x_upload_session, Unset):
+ headers["X-Upload-Session"] = x_upload_session
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/storage/{bucket_name}/{path}".format(bucket_name=quote(str(bucket_name), safe=""),path=quote(str(path), safe=""),),
+ }
+
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | File | None:
+ if response.status_code == 200:
+ response_200 = File(
+ payload = BytesIO(response.content)
+ )
+
+
+
+ return response_200
+
+ if response.status_code == 206:
+ response_206 = cast(Any, None)
+ return response_206
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error | File]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ range_: str | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Response[Any | Error | File]:
+ """ Download a file or get upload session status
+
+ Download a file, or get the status of a resumable upload session.
+
+ **File Download (default):**
+ Downloads the file at the specified path.
+
+ **Session Status (with X-Upload-Session header):**
+ Returns the status of a resumable upload session, including which parts have been uploaded.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ range_ (str | Unset):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | File]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+range_=range_,
+x_upload_session=x_upload_session,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ range_: str | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Any | Error | File | None:
+ """ Download a file or get upload session status
+
+ Download a file, or get the status of a resumable upload session.
+
+ **File Download (default):**
+ Downloads the file at the specified path.
+
+ **Session Status (with X-Upload-Session header):**
+ Returns the status of a resumable upload session, including which parts have been uploaded.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ range_ (str | Unset):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | File
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+range_=range_,
+x_upload_session=x_upload_session,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ range_: str | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Response[Any | Error | File]:
+ """ Download a file or get upload session status
+
+ Download a file, or get the status of a resumable upload session.
+
+ **File Download (default):**
+ Downloads the file at the specified path.
+
+ **Session Status (with X-Upload-Session header):**
+ Returns the status of a resumable upload session, including which parts have been uploaded.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ range_ (str | Unset):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | File]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+range_=range_,
+x_upload_session=x_upload_session,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ range_: str | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+
+) -> Any | Error | File | None:
+ """ Download a file or get upload session status
+
+ Download a file, or get the status of a resumable upload session.
+
+ **File Download (default):**
+ Downloads the file at the specified path.
+
+ **Session Status (with X-Upload-Session header):**
+ Returns the status of a resumable upload session, including which parts have been uploaded.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ range_ (str | Unset):
+ x_upload_session (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | File
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+range_=range_,
+x_upload_session=x_upload_session,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/list_storage_objects.py b/src/volcano_sdk/_generated/api/storage_objects/list_storage_objects.py
new file mode 100644
index 00000000..c7cdb40d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/list_storage_objects.py
@@ -0,0 +1,235 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.storage_list_response import StorageListResponse
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ *,
+ prefix: str | Unset = UNSET,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["prefix"] = prefix
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/storage/{bucket_name}".format(bucket_name=quote(str(bucket_name), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | StorageListResponse | None:
+ if response.status_code == 200:
+ response_200 = StorageListResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error | StorageListResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ prefix: str | Unset = UNSET,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+
+) -> Response[Any | Error | StorageListResponse]:
+ """ List objects in a bucket
+
+ Args:
+ bucket_name (str):
+ prefix (str | Unset):
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | StorageListResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+prefix=prefix,
+limit=limit,
+cursor=cursor,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ prefix: str | Unset = UNSET,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+
+) -> Any | Error | StorageListResponse | None:
+ """ List objects in a bucket
+
+ Args:
+ bucket_name (str):
+ prefix (str | Unset):
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | StorageListResponse
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+client=client,
+prefix=prefix,
+limit=limit,
+cursor=cursor,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ prefix: str | Unset = UNSET,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+
+) -> Response[Any | Error | StorageListResponse]:
+ """ List objects in a bucket
+
+ Args:
+ bucket_name (str):
+ prefix (str | Unset):
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | StorageListResponse]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+prefix=prefix,
+limit=limit,
+cursor=cursor,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ prefix: str | Unset = UNSET,
+ limit: int | Unset = 50,
+ cursor: str | Unset = UNSET,
+
+) -> Any | Error | StorageListResponse | None:
+ """ List objects in a bucket
+
+ Args:
+ bucket_name (str):
+ prefix (str | Unset):
+ limit (int | Unset): Default: 50.
+ cursor (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | StorageListResponse
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+client=client,
+prefix=prefix,
+limit=limit,
+cursor=cursor,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/move_storage_object.py b/src/volcano_sdk/_generated/api/storage_objects/move_storage_object.py
new file mode 100644
index 00000000..d87d6555
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/move_storage_object.py
@@ -0,0 +1,203 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.storage_move_request import StorageMoveRequest
+from ...models.storage_object import StorageObject
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ *,
+ body: StorageMoveRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/storage/{bucket_name}/move".format(bucket_name=quote(str(bucket_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | StorageObject | None:
+ if response.status_code == 200:
+ response_200 = StorageObject.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error | StorageObject]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageMoveRequest,
+
+) -> Response[Any | Error | StorageObject]:
+ """ Move/rename an object
+
+ Args:
+ bucket_name (str):
+ body (StorageMoveRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | StorageObject]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageMoveRequest,
+
+) -> Any | Error | StorageObject | None:
+ """ Move/rename an object
+
+ Args:
+ bucket_name (str):
+ body (StorageMoveRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | StorageObject
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageMoveRequest,
+
+) -> Response[Any | Error | StorageObject]:
+ """ Move/rename an object
+
+ Args:
+ bucket_name (str):
+ body (StorageMoveRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error | StorageObject]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageMoveRequest,
+
+) -> Any | Error | StorageObject | None:
+ """ Move/rename an object
+
+ Args:
+ bucket_name (str):
+ body (StorageMoveRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error | StorageObject
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/update_storage_object_visibility.py b/src/volcano_sdk/_generated/api/storage_objects/update_storage_object_visibility.py
new file mode 100644
index 00000000..6943782b
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/update_storage_object_visibility.py
@@ -0,0 +1,244 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.storage_object import StorageObject
+from ...models.storage_visibility_request import StorageVisibilityRequest
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ path: str,
+ *,
+ body: StorageVisibilityRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "patch",
+ "url": "/storage/{bucket_name}/{path}/visibility".format(bucket_name=quote(str(bucket_name), safe=""),path=quote(str(path), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | StorageObject | None:
+ if response.status_code == 200:
+ response_200 = StorageObject.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | StorageObject]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageVisibilityRequest,
+
+) -> Response[Any | StorageObject]:
+ """ Update file visibility (public/private)
+
+ Change whether a file is publicly accessible. Only the file owner or a service key can change
+ visibility.
+ If the bucket defines UPDATE policies, the owner must also satisfy one of them.
+
+ - Public files can be downloaded with just an anon key (no user authentication required)
+ - Private files (default) require authentication and must pass policy checks
+ - All downloads go through the Volcano API - there is no direct access to the underlying store
+
+ Args:
+ bucket_name (str):
+ path (str):
+ body (StorageVisibilityRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | StorageObject]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageVisibilityRequest,
+
+) -> Any | StorageObject | None:
+ """ Update file visibility (public/private)
+
+ Change whether a file is publicly accessible. Only the file owner or a service key can change
+ visibility.
+ If the bucket defines UPDATE policies, the owner must also satisfy one of them.
+
+ - Public files can be downloaded with just an anon key (no user authentication required)
+ - Private files (default) require authentication and must pass policy checks
+ - All downloads go through the Volcano API - there is no direct access to the underlying store
+
+ Args:
+ bucket_name (str):
+ path (str):
+ body (StorageVisibilityRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | StorageObject
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageVisibilityRequest,
+
+) -> Response[Any | StorageObject]:
+ """ Update file visibility (public/private)
+
+ Change whether a file is publicly accessible. Only the file owner or a service key can change
+ visibility.
+ If the bucket defines UPDATE policies, the owner must also satisfy one of them.
+
+ - Public files can be downloaded with just an anon key (no user authentication required)
+ - Private files (default) require authentication and must pass policy checks
+ - All downloads go through the Volcano API - there is no direct access to the underlying store
+
+ Args:
+ bucket_name (str):
+ path (str):
+ body (StorageVisibilityRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | StorageObject]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: StorageVisibilityRequest,
+
+) -> Any | StorageObject | None:
+ """ Update file visibility (public/private)
+
+ Change whether a file is publicly accessible. Only the file owner or a service key can change
+ visibility.
+ If the bucket defines UPDATE policies, the owner must also satisfy one of them.
+
+ - Public files can be downloaded with just an anon key (no user authentication required)
+ - Private files (default) require authentication and must pass policy checks
+ - All downloads go through the Volcano API - there is no direct access to the underlying store
+
+ Args:
+ bucket_name (str):
+ path (str):
+ body (StorageVisibilityRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | StorageObject
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/upload_part.py b/src/volcano_sdk/_generated/api/storage_objects/upload_part.py
new file mode 100644
index 00000000..9bccc92f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/upload_part.py
@@ -0,0 +1,283 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.upload_session_part import UploadSessionPart
+from ...types import File, FileTypes
+from io import BytesIO
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ path: str,
+ *,
+ body: File,
+ x_upload_session: str,
+ x_part_number: int,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ headers["X-Upload-Session"] = x_upload_session
+
+ headers["X-Part-Number"] = str(x_part_number)
+
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/storage/{bucket_name}/{path}".format(bucket_name=quote(str(bucket_name), safe=""),path=quote(str(path), safe=""),),
+ }
+
+ _kwargs["content"] = body.payload
+ headers["Content-Type"] = "application/octet-stream"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | UploadSessionPart | None:
+ if response.status_code == 200:
+ response_200 = UploadSessionPart.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 404:
+ response_404 = cast(Any, None)
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | UploadSessionPart]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: File,
+ x_upload_session: str,
+ x_part_number: int,
+
+) -> Response[Any | UploadSessionPart]:
+ """ Upload a part of a resumable upload
+
+ Upload a single part of a resumable upload session.
+
+ **Requirements:**
+ - Part numbers start at 1
+ - All parts except the last must be at least 5MB
+ - Maximum part size is 25MB
+ - Parts can be uploaded in any order
+ - Re-uploading a part overwrites the previous upload
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str):
+ x_part_number (int):
+ body (File):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | UploadSessionPart]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+body=body,
+x_upload_session=x_upload_session,
+x_part_number=x_part_number,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: File,
+ x_upload_session: str,
+ x_part_number: int,
+
+) -> Any | UploadSessionPart | None:
+ """ Upload a part of a resumable upload
+
+ Upload a single part of a resumable upload session.
+
+ **Requirements:**
+ - Part numbers start at 1
+ - All parts except the last must be at least 5MB
+ - Maximum part size is 25MB
+ - Parts can be uploaded in any order
+ - Re-uploading a part overwrites the previous upload
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str):
+ x_part_number (int):
+ body (File):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | UploadSessionPart
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+body=body,
+x_upload_session=x_upload_session,
+x_part_number=x_part_number,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: File,
+ x_upload_session: str,
+ x_part_number: int,
+
+) -> Response[Any | UploadSessionPart]:
+ """ Upload a part of a resumable upload
+
+ Upload a single part of a resumable upload session.
+
+ **Requirements:**
+ - Part numbers start at 1
+ - All parts except the last must be at least 5MB
+ - Maximum part size is 25MB
+ - Parts can be uploaded in any order
+ - Re-uploading a part overwrites the previous upload
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str):
+ x_part_number (int):
+ body (File):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | UploadSessionPart]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+body=body,
+x_upload_session=x_upload_session,
+x_part_number=x_part_number,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: File,
+ x_upload_session: str,
+ x_part_number: int,
+
+) -> Any | UploadSessionPart | None:
+ """ Upload a part of a resumable upload
+
+ Upload a single part of a resumable upload session.
+
+ **Requirements:**
+ - Part numbers start at 1
+ - All parts except the last must be at least 5MB
+ - Maximum part size is 25MB
+ - Parts can be uploaded in any order
+ - Re-uploading a part overwrites the previous upload
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str):
+ x_part_number (int):
+ body (File):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | UploadSessionPart
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+body=body,
+x_upload_session=x_upload_session,
+x_part_number=x_part_number,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_objects/upload_storage_object.py b/src/volcano_sdk/_generated/api/storage_objects/upload_storage_object.py
new file mode 100644
index 00000000..a74b9012
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_objects/upload_storage_object.py
@@ -0,0 +1,352 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.complete_upload_session_response import CompleteUploadSessionResponse
+from ...models.create_upload_session_request import CreateUploadSessionRequest
+from ...models.create_upload_session_response import CreateUploadSessionResponse
+from ...models.error import Error
+from ...models.storage_object import StorageObject
+from ...models.upload_storage_object_files_body import UploadStorageObjectFilesBody
+from ...models.upload_storage_object_x_upload_complete import check_upload_storage_object_x_upload_complete
+from ...models.upload_storage_object_x_upload_complete import UploadStorageObjectXUploadComplete
+from ...types import UNSET, Unset
+from typing import cast
+
+
+
+def _get_kwargs(
+ bucket_name: str,
+ path: str,
+ *,
+ body: UploadStorageObjectFilesBody | CreateUploadSessionRequest | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+ x_upload_complete: UploadStorageObjectXUploadComplete | Unset = UNSET,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+ if not isinstance(x_upload_session, Unset):
+ headers["X-Upload-Session"] = x_upload_session
+
+ if not isinstance(x_upload_complete, Unset):
+ headers["X-Upload-Complete"] = str(x_upload_complete)
+
+
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/storage/{bucket_name}/{path}".format(bucket_name=quote(str(bucket_name), safe=""),path=quote(str(path), safe=""),),
+ }
+
+ if isinstance(body, UploadStorageObjectFilesBody):
+ _kwargs["files"] = body.to_multipart()
+
+ headers["Content-Type"] = "multipart/form-data; boundary=+++"
+ if isinstance(body, CreateUploadSessionRequest):
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error | None:
+ if response.status_code == 200:
+ response_200 = CompleteUploadSessionResponse.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 201:
+ def _parse_response_201(data: object) -> CreateUploadSessionResponse | StorageObject:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ response_201_type_0 = StorageObject.from_dict(data)
+
+
+
+ return response_201_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ response_201_type_1 = CreateUploadSessionResponse.from_dict(data)
+
+
+
+ return response_201_type_1
+
+ response_201 = _parse_response_201(response.json())
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = cast(Any, None)
+ return response_400
+
+ if response.status_code == 403:
+ response_403 = cast(Any, None)
+ return response_403
+
+ if response.status_code == 413:
+ response_413 = cast(Any, None)
+ return response_413
+
+ if response.status_code == 429:
+ response_429 = Error.from_dict(response.json())
+
+
+
+ return response_429
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: UploadStorageObjectFilesBody | CreateUploadSessionRequest | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+ x_upload_complete: UploadStorageObjectXUploadComplete | Unset = UNSET,
+
+) -> Response[Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error]:
+ r""" Upload a file or create resumable session
+
+ Unified endpoint for file uploads. Behavior depends on Content-Type and headers:
+
+ **Simple Upload (multipart/form-data):**
+ Upload a complete file in a single request. Best for files under 100MB.
+
+ **Create Resumable Session (application/json):**
+ Create a session for chunked uploads. Best for large files or unreliable networks.
+ Requires: `Content-Type: application/json` with body `{\"filename\": \"...\", \"content_type\":
+ \"...\", \"total_size\": ...}`
+
+ **Complete Resumable Session:**
+ Complete a session after all parts are uploaded.
+ Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+ x_upload_complete (UploadStorageObjectXUploadComplete | Unset):
+ body (UploadStorageObjectFilesBody):
+ body (CreateUploadSessionRequest): Request to create a resumable upload session
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+body=body,
+x_upload_session=x_upload_session,
+x_upload_complete=x_upload_complete,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: UploadStorageObjectFilesBody | CreateUploadSessionRequest | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+ x_upload_complete: UploadStorageObjectXUploadComplete | Unset = UNSET,
+
+) -> Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error | None:
+ r""" Upload a file or create resumable session
+
+ Unified endpoint for file uploads. Behavior depends on Content-Type and headers:
+
+ **Simple Upload (multipart/form-data):**
+ Upload a complete file in a single request. Best for files under 100MB.
+
+ **Create Resumable Session (application/json):**
+ Create a session for chunked uploads. Best for large files or unreliable networks.
+ Requires: `Content-Type: application/json` with body `{\"filename\": \"...\", \"content_type\":
+ \"...\", \"total_size\": ...}`
+
+ **Complete Resumable Session:**
+ Complete a session after all parts are uploaded.
+ Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+ x_upload_complete (UploadStorageObjectXUploadComplete | Unset):
+ body (UploadStorageObjectFilesBody):
+ body (CreateUploadSessionRequest): Request to create a resumable upload session
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error
+ """
+
+
+ return sync_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+body=body,
+x_upload_session=x_upload_session,
+x_upload_complete=x_upload_complete,
+
+ ).parsed
+
+async def asyncio_detailed(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: UploadStorageObjectFilesBody | CreateUploadSessionRequest | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+ x_upload_complete: UploadStorageObjectXUploadComplete | Unset = UNSET,
+
+) -> Response[Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error]:
+ r""" Upload a file or create resumable session
+
+ Unified endpoint for file uploads. Behavior depends on Content-Type and headers:
+
+ **Simple Upload (multipart/form-data):**
+ Upload a complete file in a single request. Best for files under 100MB.
+
+ **Create Resumable Session (application/json):**
+ Create a session for chunked uploads. Best for large files or unreliable networks.
+ Requires: `Content-Type: application/json` with body `{\"filename\": \"...\", \"content_type\":
+ \"...\", \"total_size\": ...}`
+
+ **Complete Resumable Session:**
+ Complete a session after all parts are uploaded.
+ Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+ x_upload_complete (UploadStorageObjectXUploadComplete | Unset):
+ body (UploadStorageObjectFilesBody):
+ body (CreateUploadSessionRequest): Request to create a resumable upload session
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ bucket_name=bucket_name,
+path=path,
+body=body,
+x_upload_session=x_upload_session,
+x_upload_complete=x_upload_complete,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ bucket_name: str,
+ path: str,
+ *,
+ client: AuthenticatedClient,
+ body: UploadStorageObjectFilesBody | CreateUploadSessionRequest | Unset = UNSET,
+ x_upload_session: str | Unset = UNSET,
+ x_upload_complete: UploadStorageObjectXUploadComplete | Unset = UNSET,
+
+) -> Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error | None:
+ r""" Upload a file or create resumable session
+
+ Unified endpoint for file uploads. Behavior depends on Content-Type and headers:
+
+ **Simple Upload (multipart/form-data):**
+ Upload a complete file in a single request. Best for files under 100MB.
+
+ **Create Resumable Session (application/json):**
+ Create a session for chunked uploads. Best for large files or unreliable networks.
+ Requires: `Content-Type: application/json` with body `{\"filename\": \"...\", \"content_type\":
+ \"...\", \"total_size\": ...}`
+
+ **Complete Resumable Session:**
+ Complete a session after all parts are uploaded.
+ Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header.
+
+ Args:
+ bucket_name (str):
+ path (str):
+ x_upload_session (str | Unset):
+ x_upload_complete (UploadStorageObjectXUploadComplete | Unset):
+ body (UploadStorageObjectFilesBody):
+ body (CreateUploadSessionRequest): Request to create a resumable upload session
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | CompleteUploadSessionResponse | CreateUploadSessionResponse | StorageObject | Error
+ """
+
+
+ return (await asyncio_detailed(
+ bucket_name=bucket_name,
+path=path,
+client=client,
+body=body,
+x_upload_session=x_upload_session,
+x_upload_complete=x_upload_complete,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_policies/__init__.py b/src/volcano_sdk/_generated/api/storage_policies/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_policies/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/storage_policies/create_storage_policy.py b/src/volcano_sdk/_generated/api/storage_policies/create_storage_policy.py
new file mode 100644
index 00000000..40a587b0
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_policies/create_storage_policy.py
@@ -0,0 +1,205 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_storage_policy_request import CreateStoragePolicyRequest
+from ...models.storage_policy import StoragePolicy
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ bucket_name: str,
+ *,
+ body: CreateStoragePolicyRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/storage/buckets/{bucket_name}/policies".format(id=quote(str(id), safe=""),bucket_name=quote(str(bucket_name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> StoragePolicy | None:
+ if response.status_code == 201:
+ response_201 = StoragePolicy.from_dict(response.json())
+
+
+
+ return response_201
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[StoragePolicy]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStoragePolicyRequest,
+
+) -> Response[StoragePolicy]:
+ """ Create a storage policy
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (CreateStoragePolicyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[StoragePolicy]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStoragePolicyRequest,
+
+) -> StoragePolicy | None:
+ """ Create a storage policy
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (CreateStoragePolicyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ StoragePolicy
+ """
+
+
+ return sync_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStoragePolicyRequest,
+
+) -> Response[StoragePolicy]:
+ """ Create a storage policy
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (CreateStoragePolicyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[StoragePolicy]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+ body: CreateStoragePolicyRequest,
+
+) -> StoragePolicy | None:
+ """ Create a storage policy
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ body (CreateStoragePolicyRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ StoragePolicy
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/storage_policies/delete_storage_policy.py b/src/volcano_sdk/_generated/api/storage_policies/delete_storage_policy.py
new file mode 100644
index 00000000..104714b3
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_policies/delete_storage_policy.py
@@ -0,0 +1,130 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ bucket_name: str,
+ policy_id: UUID,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/storage/buckets/{bucket_name}/policies/{policy_id}".format(id=quote(str(id), safe=""),bucket_name=quote(str(bucket_name), safe=""),policy_id=quote(str(policy_id), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | None:
+ if response.status_code == 200:
+ return None
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ bucket_name: str,
+ policy_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete a storage policy
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ policy_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+policy_id=policy_id,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: UUID,
+ bucket_name: str,
+ policy_id: UUID,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any]:
+ """ Delete a storage policy
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+ policy_id (UUID):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+policy_id=policy_id,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
diff --git a/src/volcano_sdk/_generated/api/storage_policies/list_storage_policies.py b/src/volcano_sdk/_generated/api/storage_policies/list_storage_policies.py
new file mode 100644
index 00000000..24e8eb6a
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/storage_policies/list_storage_policies.py
@@ -0,0 +1,190 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.storage_policy import StoragePolicy
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ bucket_name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/storage/buckets/{bucket_name}/policies".format(id=quote(str(id), safe=""),bucket_name=quote(str(bucket_name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> list[StoragePolicy] | None:
+ if response.status_code == 200:
+ response_200 = []
+ _response_200 = response.json()
+ for response_200_item_data in (_response_200):
+ response_200_item = StoragePolicy.from_dict(response_200_item_data)
+
+
+
+ response_200.append(response_200_item)
+
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[list[StoragePolicy]]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[list[StoragePolicy]]:
+ """ List storage policies for a bucket
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[StoragePolicy]]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> list[StoragePolicy] | None:
+ """ List storage policies for a bucket
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[StoragePolicy]
+ """
+
+
+ return sync_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[list[StoragePolicy]]:
+ """ List storage policies for a bucket
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[list[StoragePolicy]]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+bucket_name=bucket_name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ bucket_name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> list[StoragePolicy] | None:
+ """ List storage policies for a bucket
+
+ Args:
+ id (UUID):
+ bucket_name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ list[StoragePolicy]
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+bucket_name=bucket_name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/system/__init__.py b/src/volcano_sdk/_generated/api/system/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/system/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/system/health_check.py b/src/volcano_sdk/_generated/api/system/health_check.py
new file mode 100644
index 00000000..608c024e
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/system/health_check.py
@@ -0,0 +1,153 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+
+
+
+def _get_kwargs(
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/health",
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> str | None:
+ if response.status_code == 200:
+ response_200 = response.text
+ return response_200
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[str]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[str]:
+ """ Health check endpoint
+
+ Returns server health status. Used for load balancer and monitoring checks.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[str]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> str | None:
+ """ Health check endpoint
+
+ Returns server health status. Used for load balancer and monitoring checks.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ str
+ """
+
+
+ return sync_detailed(
+ client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> Response[str]:
+ """ Health check endpoint
+
+ Returns server health status. Used for load balancer and monitoring checks.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[str]
+ """
+
+
+ kwargs = _get_kwargs(
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ *,
+ client: AuthenticatedClient | Client,
+
+) -> str | None:
+ """ Health check endpoint
+
+ Returns server health status. Used for load balancer and monitoring checks.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ str
+ """
+
+
+ return (await asyncio_detailed(
+ client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/variables/__init__.py b/src/volcano_sdk/_generated/api/variables/__init__.py
new file mode 100644
index 00000000..c9921b5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/variables/__init__.py
@@ -0,0 +1 @@
+""" Contains endpoint functions for accessing the API """
diff --git a/src/volcano_sdk/_generated/api/variables/create_variable.py b/src/volcano_sdk/_generated/api/variables/create_variable.py
new file mode 100644
index 00000000..2e73ecdc
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/variables/create_variable.py
@@ -0,0 +1,212 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.create_variable_request import CreateVariableRequest
+from ...models.error import Error
+from ...models.variable import Variable
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ body: CreateVariableRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "post",
+ "url": "/projects/{id}/variables".format(id=quote(str(id), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Variable | None:
+ if response.status_code == 201:
+ response_201 = Variable.from_dict(response.json())
+
+
+
+ return response_201
+
+ if response.status_code == 400:
+ response_400 = Error.from_dict(response.json())
+
+
+
+ return response_400
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Variable]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateVariableRequest,
+
+) -> Response[Error | Variable]:
+ """ Create or update a variable
+
+ Creates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ body (CreateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Variable]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateVariableRequest,
+
+) -> Error | Variable | None:
+ """ Create or update a variable
+
+ Creates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ body (CreateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Variable
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateVariableRequest,
+
+) -> Response[Error | Variable]:
+ """ Create or update a variable
+
+ Creates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ body (CreateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Variable]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ body: CreateVariableRequest,
+
+) -> Error | Variable | None:
+ """ Create or update a variable
+
+ Creates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ body (CreateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Variable
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/variables/delete_variable.py b/src/volcano_sdk/_generated/api/variables/delete_variable.py
new file mode 100644
index 00000000..589d4a1d
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/variables/delete_variable.py
@@ -0,0 +1,201 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "delete",
+ "url": "/projects/{id}/variables/{name}".format(id=quote(str(id), safe=""),name=quote(str(name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | Error | None:
+ if response.status_code == 204:
+ response_204 = cast(Any, None)
+ return response_204
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | Error]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a variable
+
+ Deletes a project-level environment variable and triggers asynchronous propagation
+ of the removal to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+name=name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a variable
+
+ Deletes a project-level environment variable and triggers asynchronous propagation
+ of the removal to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return sync_detailed(
+ id=id,
+name=name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Any | Error]:
+ """ Delete a variable
+
+ Deletes a project-level environment variable and triggers asynchronous propagation
+ of the removal to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any | Error]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+name=name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Any | Error | None:
+ """ Delete a variable
+
+ Deletes a project-level environment variable and triggers asynchronous propagation
+ of the removal to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Any | Error
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+name=name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/variables/get_variable.py b/src/volcano_sdk/_generated/api/variables/get_variable.py
new file mode 100644
index 00000000..3c561db1
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/variables/get_variable.py
@@ -0,0 +1,201 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.variable import Variable
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ name: str,
+
+) -> dict[str, Any]:
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/variables/{name}".format(id=quote(str(id), safe=""),name=quote(str(name), safe=""),),
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Variable | None:
+ if response.status_code == 200:
+ response_200 = Variable.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Variable]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Variable]:
+ """ Get variable by name
+
+ Returns a project-level environment variable used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Variable]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+name=name,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Variable | None:
+ """ Get variable by name
+
+ Returns a project-level environment variable used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Variable
+ """
+
+
+ return sync_detailed(
+ id=id,
+name=name,
+client=client,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Response[Error | Variable]:
+ """ Get variable by name
+
+ Returns a project-level environment variable used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Variable]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+name=name,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+
+) -> Error | Variable | None:
+ """ Get variable by name
+
+ Returns a project-level environment variable used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ name (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Variable
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+name=name,
+client=client,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/variables/list_variables.py b/src/volcano_sdk/_generated/api/variables/list_variables.py
new file mode 100644
index 00000000..56562d46
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/variables/list_variables.py
@@ -0,0 +1,285 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.paginated_variables import PaginatedVariables
+from ...types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ *,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> dict[str, Any]:
+
+
+
+
+ params: dict[str, Any] = {}
+
+ params["page"] = page
+
+ params["limit"] = limit
+
+ params["cursor"] = cursor
+
+ params["ending_before"] = ending_before
+
+ params["offset"] = offset
+
+ params["search"] = search
+
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "get",
+ "url": "/projects/{id}/variables".format(id=quote(str(id), safe=""),),
+ "params": params,
+ }
+
+
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | PaginatedVariables | None:
+ if response.status_code == 200:
+ response_200 = PaginatedVariables.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | PaginatedVariables]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedVariables]:
+ """ List all variables for a project
+
+ Returns project-level environment variables used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedVariables]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedVariables | None:
+ """ List all variables for a project
+
+ Returns project-level environment variables used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedVariables
+ """
+
+
+ return sync_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Response[Error | PaginatedVariables]:
+ """ List all variables for a project
+
+ Returns project-level environment variables used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | PaginatedVariables]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ *,
+ client: AuthenticatedClient,
+ page: int | Unset = UNSET,
+ limit: int | Unset = 10,
+ cursor: str | Unset = UNSET,
+ ending_before: str | Unset = UNSET,
+ offset: int | Unset = 0,
+ search: str | Unset = UNSET,
+
+) -> Error | PaginatedVariables | None:
+ """ List all variables for a project
+
+ Returns project-level environment variables used by deployed functions and frontends.
+
+ Args:
+ id (UUID):
+ page (int | Unset):
+ limit (int | Unset): Default: 10.
+ cursor (str | Unset):
+ ending_before (str | Unset):
+ offset (int | Unset): Default: 0.
+ search (str | Unset):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | PaginatedVariables
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+client=client,
+page=page,
+limit=limit,
+cursor=cursor,
+ending_before=ending_before,
+offset=offset,
+search=search,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/api/variables/update_variable.py b/src/volcano_sdk/_generated/api/variables/update_variable.py
new file mode 100644
index 00000000..4db0bbfc
--- /dev/null
+++ b/src/volcano_sdk/_generated/api/variables/update_variable.py
@@ -0,0 +1,225 @@
+from http import HTTPStatus
+from typing import Any, cast
+from urllib.parse import quote
+
+import httpx
+
+from ...client import AuthenticatedClient, Client
+from ...types import Response, UNSET
+from ... import errors
+
+from ...models.error import Error
+from ...models.update_variable_request import UpdateVariableRequest
+from ...models.variable import Variable
+from typing import cast
+from uuid import UUID
+
+
+
+def _get_kwargs(
+ id: UUID,
+ name: str,
+ *,
+ body: UpdateVariableRequest,
+
+) -> dict[str, Any]:
+ headers: dict[str, Any] = {}
+
+
+
+
+
+
+ _kwargs: dict[str, Any] = {
+ "method": "put",
+ "url": "/projects/{id}/variables/{name}".format(id=quote(str(id), safe=""),name=quote(str(name), safe=""),),
+ }
+
+ _kwargs["json"] = body.to_dict()
+
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+
+def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Error | Variable | None:
+ if response.status_code == 200:
+ response_200 = Variable.from_dict(response.json())
+
+
+
+ return response_200
+
+ if response.status_code == 404:
+ response_404 = Error.from_dict(response.json())
+
+
+
+ return response_404
+
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Error | Variable]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateVariableRequest,
+
+) -> Response[Error | Variable]:
+ """ Update a variable
+
+ Updates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+ body (UpdateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Variable]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+name=name,
+body=body,
+
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+def sync(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateVariableRequest,
+
+) -> Error | Variable | None:
+ """ Update a variable
+
+ Updates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+ body (UpdateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Variable
+ """
+
+
+ return sync_detailed(
+ id=id,
+name=name,
+client=client,
+body=body,
+
+ ).parsed
+
+async def asyncio_detailed(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateVariableRequest,
+
+) -> Response[Error | Variable]:
+ """ Update a variable
+
+ Updates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+ body (UpdateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Error | Variable]
+ """
+
+
+ kwargs = _get_kwargs(
+ id=id,
+name=name,
+body=body,
+
+ )
+
+ response = await client.get_async_httpx_client().request(
+ **kwargs
+ )
+
+ return _build_response(client=client, response=response)
+
+async def asyncio(
+ id: UUID,
+ name: str,
+ *,
+ client: AuthenticatedClient,
+ body: UpdateVariableRequest,
+
+) -> Error | Variable | None:
+ """ Update a variable
+
+ Updates a project-level environment variable and triggers asynchronous propagation
+ to deployed functions and frontends in the project's configured regions.
+
+ Args:
+ id (UUID):
+ name (str):
+ body (UpdateVariableRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Error | Variable
+ """
+
+
+ return (await asyncio_detailed(
+ id=id,
+name=name,
+client=client,
+body=body,
+
+ )).parsed
diff --git a/src/volcano_sdk/_generated/client.py b/src/volcano_sdk/_generated/client.py
new file mode 100644
index 00000000..5eeb05a0
--- /dev/null
+++ b/src/volcano_sdk/_generated/client.py
@@ -0,0 +1,271 @@
+import ssl
+from typing import Any
+
+from attrs import define, field, evolve
+import httpx
+
+
+
+
+
+@define
+class Client:
+ """A class for keeping track of data related to the API
+
+ The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
+
+ ``base_url``: The base URL for the API, all requests are made to a relative path to this URL
+
+ ``cookies``: A dictionary of cookies to be sent with every request
+
+ ``headers``: A dictionary of headers to be sent with every request
+
+ ``timeout``: The maximum amount of a time a request can take. API functions will raise
+ httpx.TimeoutException if this is exceeded.
+
+ ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
+ but can be set to False for testing purposes.
+
+ ``follow_redirects``: Whether or not to follow redirects. Default value is False.
+
+ ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
+
+
+ Attributes:
+ raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
+ status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
+ argument to the constructor.
+ """
+ raise_on_unexpected_status: bool = field(default=False, kw_only=True)
+ _base_url: str = field(alias="base_url")
+ _cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
+ _headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
+ _timeout: httpx.Timeout | None = field(default=None, kw_only=True, alias="timeout")
+ _verify_ssl: str | bool | ssl.SSLContext = field(default=True, kw_only=True, alias="verify_ssl")
+ _follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
+ _httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
+ _client: httpx.Client | None = field(default=None, init=False)
+ _async_client: httpx.AsyncClient | None = field(default=None, init=False)
+
+ def with_headers(self, headers: dict[str, str]) -> "Client":
+ """Get a new client matching this one with additional headers"""
+ if self._client is not None:
+ self._client.headers.update(headers)
+ if self._async_client is not None:
+ self._async_client.headers.update(headers)
+ return evolve(self, headers={**self._headers, **headers})
+
+ def with_cookies(self, cookies: dict[str, str]) -> "Client":
+ """Get a new client matching this one with additional cookies"""
+ if self._client is not None:
+ self._client.cookies.update(cookies)
+ if self._async_client is not None:
+ self._async_client.cookies.update(cookies)
+ return evolve(self, cookies={**self._cookies, **cookies})
+
+ def with_timeout(self, timeout: httpx.Timeout) -> "Client":
+ """Get a new client matching this one with a new timeout configuration"""
+ if self._client is not None:
+ self._client.timeout = timeout
+ if self._async_client is not None:
+ self._async_client.timeout = timeout
+ return evolve(self, timeout=timeout)
+
+ def set_httpx_client(self, client: httpx.Client) -> "Client":
+ """Manually set the underlying httpx.Client
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._client = client
+ return self
+
+ def get_httpx_client(self) -> httpx.Client:
+ """Get the underlying httpx.Client, constructing a new one if not previously set"""
+ if self._client is None:
+ self._client = httpx.Client(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._client
+
+ def __enter__(self) -> "Client":
+ """Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
+ self.get_httpx_client().__enter__()
+ return self
+
+ def __exit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for internal httpx.Client (see httpx docs)"""
+ self.get_httpx_client().__exit__(*args, **kwargs)
+
+ def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client":
+ """Manually set the underlying httpx.AsyncClient
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._async_client = async_client
+ return self
+
+ def get_async_httpx_client(self) -> httpx.AsyncClient:
+ """Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
+ if self._async_client is None:
+ self._async_client = httpx.AsyncClient(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._async_client
+
+ async def __aenter__(self) -> "Client":
+ """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
+ await self.get_async_httpx_client().__aenter__()
+ return self
+
+ async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
+ await self.get_async_httpx_client().__aexit__(*args, **kwargs)
+
+
+@define
+class AuthenticatedClient:
+ """A Client which has been authenticated for use on secured endpoints
+
+ The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
+
+ ``base_url``: The base URL for the API, all requests are made to a relative path to this URL
+
+ ``cookies``: A dictionary of cookies to be sent with every request
+
+ ``headers``: A dictionary of headers to be sent with every request
+
+ ``timeout``: The maximum amount of a time a request can take. API functions will raise
+ httpx.TimeoutException if this is exceeded.
+
+ ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
+ but can be set to False for testing purposes.
+
+ ``follow_redirects``: Whether or not to follow redirects. Default value is False.
+
+ ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
+
+
+ Attributes:
+ raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
+ status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
+ argument to the constructor.
+ token: The token to use for authentication
+ prefix: The prefix to use for the Authorization header
+ auth_header_name: The name of the Authorization header
+ """
+
+ raise_on_unexpected_status: bool = field(default=False, kw_only=True)
+ _base_url: str = field(alias="base_url")
+ _cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
+ _headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
+ _timeout: httpx.Timeout | None = field(default=None, kw_only=True, alias="timeout")
+ _verify_ssl: str | bool | ssl.SSLContext = field(default=True, kw_only=True, alias="verify_ssl")
+ _follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
+ _httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
+ _client: httpx.Client | None = field(default=None, init=False)
+ _async_client: httpx.AsyncClient | None = field(default=None, init=False)
+
+ token: str
+ prefix: str = "Bearer"
+ auth_header_name: str = "Authorization"
+
+ def with_headers(self, headers: dict[str, str]) -> "AuthenticatedClient":
+ """Get a new client matching this one with additional headers"""
+ if self._client is not None:
+ self._client.headers.update(headers)
+ if self._async_client is not None:
+ self._async_client.headers.update(headers)
+ return evolve(self, headers={**self._headers, **headers})
+
+ def with_cookies(self, cookies: dict[str, str]) -> "AuthenticatedClient":
+ """Get a new client matching this one with additional cookies"""
+ if self._client is not None:
+ self._client.cookies.update(cookies)
+ if self._async_client is not None:
+ self._async_client.cookies.update(cookies)
+ return evolve(self, cookies={**self._cookies, **cookies})
+
+ def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient":
+ """Get a new client matching this one with a new timeout configuration"""
+ if self._client is not None:
+ self._client.timeout = timeout
+ if self._async_client is not None:
+ self._async_client.timeout = timeout
+ return evolve(self, timeout=timeout)
+
+ def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient":
+ """Manually set the underlying httpx.Client
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._client = client
+ return self
+
+ def get_httpx_client(self) -> httpx.Client:
+ """Get the underlying httpx.Client, constructing a new one if not previously set"""
+ if self._client is None:
+ self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
+ self._client = httpx.Client(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._client
+
+ def __enter__(self) -> "AuthenticatedClient":
+ """Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
+ self.get_httpx_client().__enter__()
+ return self
+
+ def __exit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for internal httpx.Client (see httpx docs)"""
+ self.get_httpx_client().__exit__(*args, **kwargs)
+
+ def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient":
+ """Manually set the underlying httpx.AsyncClient
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._async_client = async_client
+ return self
+
+ def get_async_httpx_client(self) -> httpx.AsyncClient:
+ """Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
+ if self._async_client is None:
+ self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
+ self._async_client = httpx.AsyncClient(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._async_client
+
+ async def __aenter__(self) -> "AuthenticatedClient":
+ """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
+ await self.get_async_httpx_client().__aenter__()
+ return self
+
+ async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
+ await self.get_async_httpx_client().__aexit__(*args, **kwargs)
+
diff --git a/src/volcano_sdk/_generated/errors.py b/src/volcano_sdk/_generated/errors.py
new file mode 100644
index 00000000..b912123d
--- /dev/null
+++ b/src/volcano_sdk/_generated/errors.py
@@ -0,0 +1,14 @@
+""" Contains shared errors types that can be raised from API functions """
+
+class UnexpectedStatus(Exception):
+ """Raised by api functions when the response status an undocumented status and Client.raise_on_unexpected_status is True"""
+
+ def __init__(self, status_code: int, content: bytes):
+ self.status_code = status_code
+ self.content = content
+
+ super().__init__(
+ f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}"
+ )
+
+__all__ = ["UnexpectedStatus"]
diff --git a/src/volcano_sdk/_generated/models/__init__.py b/src/volcano_sdk/_generated/models/__init__.py
new file mode 100644
index 00000000..6a618b6b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/__init__.py
@@ -0,0 +1,905 @@
+""" Contains all the data models used in inputs/outputs """
+
+from .anon_key import AnonKey
+from .auth_cancel_email_change_response_200 import AuthCancelEmailChangeResponse200
+from .auth_config import AuthConfig
+from .auth_config_allowed_email_domains_mode import AuthConfigAllowedEmailDomainsMode
+from .auth_confirm_email_body import AuthConfirmEmailBody
+from .auth_confirm_email_change_body import AuthConfirmEmailChangeBody
+from .auth_confirm_email_change_response_200 import AuthConfirmEmailChangeResponse200
+from .auth_confirm_email_response_200 import AuthConfirmEmailResponse200
+from .auth_confirm_email_response_200_message import AuthConfirmEmailResponse200Message
+from .auth_convert_anonymous_body import AuthConvertAnonymousBody
+from .auth_convert_anonymous_body_user_metadata import AuthConvertAnonymousBodyUserMetadata
+from .auth_convert_anonymous_response_200 import AuthConvertAnonymousResponse200
+from .auth_device_authorize_body import AuthDeviceAuthorizeBody
+from .auth_device_token_body import AuthDeviceTokenBody
+from .auth_device_token_body_grant_type import AuthDeviceTokenBodyGrantType
+from .auth_device_verify_body import AuthDeviceVerifyBody
+from .auth_device_verify_body_action import AuthDeviceVerifyBodyAction
+from .auth_device_verify_response_200 import AuthDeviceVerifyResponse200
+from .auth_forgot_password_body import AuthForgotPasswordBody
+from .auth_forgot_password_response_200 import AuthForgotPasswordResponse200
+from .auth_get_my_sessions_response_200 import AuthGetMySessionsResponse200
+from .auth_get_my_sessions_sort import AuthGetMySessionsSort
+from .auth_get_my_sessions_status import AuthGetMySessionsStatus
+from .auth_get_user_response_200 import AuthGetUserResponse200
+from .auth_hosted_page import AuthHostedPage
+from .auth_hosted_page_defaults import AuthHostedPageDefaults
+from .auth_hosted_page_response import AuthHostedPageResponse
+from .auth_hosted_page_runtime import AuthHostedPageRuntime
+from .auth_identities_response import AuthIdentitiesResponse
+from .auth_identity import AuthIdentity
+from .auth_insights_interval import AuthInsightsInterval
+from .auth_insights_response import AuthInsightsResponse
+from .auth_insights_series_point import AuthInsightsSeriesPoint
+from .auth_insights_summary import AuthInsightsSummary
+from .auth_insights_window import AuthInsightsWindow
+from .auth_link_o_auth_provider_provider import AuthLinkOAuthProviderProvider
+from .auth_link_o_auth_provider_response_200 import AuthLinkOAuthProviderResponse200
+from .auth_link_o_auth_provider_response_mode import AuthLinkOAuthProviderResponseMode
+from .auth_list_o_auth_providers_response_200 import AuthListOAuthProvidersResponse200
+from .auth_list_o_auth_providers_response_200_providers_item import AuthListOAuthProvidersResponse200ProvidersItem
+from .auth_logout_body import AuthLogoutBody
+from .auth_logout_body_session_mode import AuthLogoutBodySessionMode
+from .auth_method_summary import AuthMethodSummary
+from .auth_method_summary_type import AuthMethodSummaryType
+from .auth_methods_response import AuthMethodsResponse
+from .auth_o_auth_authorize_provider import AuthOAuthAuthorizeProvider
+from .auth_o_auth_authorize_response_mode import AuthOAuthAuthorizeResponseMode
+from .auth_o_auth_callback_provider import AuthOAuthCallbackProvider
+from .auth_o_auth_exchange_body import AuthOAuthExchangeBody
+from .auth_password_policy import AuthPasswordPolicy
+from .auth_platform_exchange_body import AuthPlatformExchangeBody
+from .auth_refresh_body import AuthRefreshBody
+from .auth_refresh_body_session_mode import AuthRefreshBodySessionMode
+from .auth_request_email_change_body import AuthRequestEmailChangeBody
+from .auth_request_email_change_response_200 import AuthRequestEmailChangeResponse200
+from .auth_resend_confirmation_body import AuthResendConfirmationBody
+from .auth_resend_confirmation_response_200 import AuthResendConfirmationResponse200
+from .auth_reset_password_body import AuthResetPasswordBody
+from .auth_reset_password_response_200 import AuthResetPasswordResponse200
+from .auth_session import AuthSession
+from .auth_session_provider import AuthSessionProvider
+from .auth_signin_body import AuthSigninBody
+from .auth_signin_body_session_mode import AuthSigninBodySessionMode
+from .auth_signup_anonymous_body import AuthSignupAnonymousBody
+from .auth_signup_anonymous_body_user_metadata import AuthSignupAnonymousBodyUserMetadata
+from .auth_signup_body import AuthSignupBody
+from .auth_signup_body_user_metadata import AuthSignupBodyUserMetadata
+from .auth_signup_response import AuthSignupResponse
+from .auth_token_response import AuthTokenResponse
+from .auth_unlink_o_auth_provider_provider import AuthUnlinkOAuthProviderProvider
+from .auth_update_user_body import AuthUpdateUserBody
+from .auth_update_user_body_user_metadata import AuthUpdateUserBodyUserMetadata
+from .auth_update_user_response_200 import AuthUpdateUserResponse200
+from .auth_user import AuthUser
+from .auth_user_app_metadata import AuthUserAppMetadata
+from .auth_user_status import AuthUserStatus
+from .auth_user_user_metadata import AuthUserUserMetadata
+from .ban_auth_user_body import BanAuthUserBody
+from .ban_user_response import BanUserResponse
+from .ban_user_response_status import BanUserResponseStatus
+from .batch_function_deploy_failure import BatchFunctionDeployFailure
+from .batch_function_deploy_failure_operation import BatchFunctionDeployFailureOperation
+from .batch_function_deploy_response import BatchFunctionDeployResponse
+from .call_o_auth_provider_api_body import CallOAuthProviderAPIBody
+from .call_o_auth_provider_api_body_body import CallOAuthProviderAPIBodyBody
+from .call_o_auth_provider_api_body_method import CallOAuthProviderAPIBodyMethod
+from .call_o_auth_provider_api_provider import CallOAuthProviderAPIProvider
+from .call_o_auth_provider_api_response_200 import CallOAuthProviderAPIResponse200
+from .complete_upload_session_response import CompleteUploadSessionResponse
+from .configure_auth_methods_body import ConfigureAuthMethodsBody
+from .configure_auth_methods_body_oauth_providers_item import ConfigureAuthMethodsBodyOauthProvidersItem
+from .connect_project_git_request import ConnectProjectGitRequest
+from .create_anon_key_body import CreateAnonKeyBody
+from .create_anon_key_body_permissions_item import CreateAnonKeyBodyPermissionsItem
+from .create_database_branch_request import CreateDatabaseBranchRequest
+from .create_database_request import CreateDatabaseRequest
+from .create_database_request_database_type import CreateDatabaseRequestDatabaseType
+from .create_database_request_pg_version import CreateDatabaseRequestPgVersion
+from .create_database_request_region import CreateDatabaseRequestRegion
+from .create_email_template_request import CreateEmailTemplateRequest
+from .create_email_template_request_template_type import CreateEmailTemplateRequestTemplateType
+from .create_frontend_body import CreateFrontendBody
+from .create_frontend_body_framework import CreateFrontendBodyFramework
+from .create_frontend_custom_domain_request import CreateFrontendCustomDomainRequest
+from .create_function_body import CreateFunctionBody
+from .create_function_body_runtime import CreateFunctionBodyRuntime
+from .create_function_scheduler_request import CreateFunctionSchedulerRequest
+from .create_function_scheduler_request_payload import CreateFunctionSchedulerRequestPayload
+from .create_functions_batch_body import CreateFunctionsBatchBody
+from .create_o_auth_config_request import CreateOAuthConfigRequest
+from .create_o_auth_config_request_provider import CreateOAuthConfigRequestProvider
+from .create_project_request import CreateProjectRequest
+from .create_service_key_body import CreateServiceKeyBody
+from .create_storage_bucket_request import CreateStorageBucketRequest
+from .create_storage_policy_request import CreateStoragePolicyRequest
+from .create_storage_policy_request_operation import CreateStoragePolicyRequestOperation
+from .create_upload_session_request import CreateUploadSessionRequest
+from .create_upload_session_response import CreateUploadSessionResponse
+from .create_variable_request import CreateVariableRequest
+from .database import Database
+from .database_branch import DatabaseBranch
+from .database_branch_list import DatabaseBranchList
+from .database_branch_status import DatabaseBranchStatus
+from .database_branch_storage import DatabaseBranchStorage
+from .database_database_type import DatabaseDatabaseType
+from .database_delete_request import DatabaseDeleteRequest
+from .database_insert_request import DatabaseInsertRequest
+from .database_insert_request_values import DatabaseInsertRequestValues
+from .database_query_filter import DatabaseQueryFilter
+from .database_query_filter_operator import DatabaseQueryFilterOperator
+from .database_query_order import DatabaseQueryOrder
+from .database_query_performance_database import DatabaseQueryPerformanceDatabase
+from .database_query_performance_item import DatabaseQueryPerformanceItem
+from .database_query_performance_response import DatabaseQueryPerformanceResponse
+from .database_query_result import DatabaseQueryResult
+from .database_query_result_data_item import DatabaseQueryResultDataItem
+from .database_select_request import DatabaseSelectRequest
+from .database_stats import DatabaseStats
+from .database_stats_granularity import DatabaseStatsGranularity
+from .database_status import DatabaseStatus
+from .database_update_request import DatabaseUpdateRequest
+from .database_update_request_values import DatabaseUpdateRequestValues
+from .delete_database_branch_response_202 import DeleteDatabaseBranchResponse202
+from .delete_database_response_202 import DeleteDatabaseResponse202
+from .delete_email_template_type import DeleteEmailTemplateType
+from .delete_o_auth_config_provider import DeleteOAuthConfigProvider
+from .deployment_phase import DeploymentPhase
+from .deployment_phase_name import DeploymentPhaseName
+from .deployment_phase_status import DeploymentPhaseStatus
+from .deployment_progress import DeploymentProgress
+from .deployment_progress_current_phase import DeploymentProgressCurrentPhase
+from .deployment_reference import DeploymentReference
+from .device_authorization_response import DeviceAuthorizationResponse
+from .email_template import EmailTemplate
+from .email_template_template_type import EmailTemplateTemplateType
+from .error import Error
+from .frontend import Frontend
+from .frontend_custom_domain_response import FrontendCustomDomainResponse
+from .frontend_custom_domain_response_domain_status import FrontendCustomDomainResponseDomainStatus
+from .frontend_custom_domain_response_tls_mode import FrontendCustomDomainResponseTlsMode
+from .frontend_custom_domain_response_verification_status import FrontendCustomDomainResponseVerificationStatus
+from .frontend_custom_domain_status import FrontendCustomDomainStatus
+from .frontend_custom_domain_tls_config import FrontendCustomDomainTLSConfig
+from .frontend_custom_domain_tls_config_mode import FrontendCustomDomainTLSConfigMode
+from .frontend_deployment import FrontendDeployment
+from .frontend_deployment_deploy_source import FrontendDeploymentDeploySource
+from .frontend_deployment_operation import FrontendDeploymentOperation
+from .frontend_deployment_status import FrontendDeploymentStatus
+from .frontend_domain_routing_record import FrontendDomainRoutingRecord
+from .frontend_domain_routing_record_record_type import FrontendDomainRoutingRecordRecordType
+from .frontend_domain_verification_record import FrontendDomainVerificationRecord
+from .frontend_framework import FrontendFramework
+from .frontend_status import FrontendStatus
+from .frontend_usage_daily_entry import FrontendUsageDailyEntry
+from .frontend_usage_data import FrontendUsageData
+from .frontend_usage_history_response import FrontendUsageHistoryResponse
+from .function import Function
+from .function_deployment import FunctionDeployment
+from .function_deployment_deploy_source import FunctionDeploymentDeploySource
+from .function_deployment_operation import FunctionDeploymentOperation
+from .function_deployment_status import FunctionDeploymentStatus
+from .function_invocation_request import FunctionInvocationRequest
+from .function_invocation_request_payload import FunctionInvocationRequestPayload
+from .function_invocation_response import FunctionInvocationResponse
+from .function_region import FunctionRegion
+from .function_runtime_deployment import FunctionRuntimeDeployment
+from .function_runtime_option import FunctionRuntimeOption
+from .function_runtimes_response import FunctionRuntimesResponse
+from .function_scheduler import FunctionScheduler
+from .function_scheduler_list_response import FunctionSchedulerListResponse
+from .function_scheduler_payload import FunctionSchedulerPayload
+from .function_scheduler_schedule_kind import FunctionSchedulerScheduleKind
+from .function_status import FunctionStatus
+from .get_auth_methods_response_200 import GetAuthMethodsResponse200
+from .get_auth_methods_response_200_anonymous import GetAuthMethodsResponse200Anonymous
+from .get_auth_methods_response_200_email_password import GetAuthMethodsResponse200EmailPassword
+from .get_auth_methods_response_200_oauth_providers_item import GetAuthMethodsResponse200OauthProvidersItem
+from .get_database_stats_granularity import GetDatabaseStatsGranularity
+from .get_default_email_template_type import GetDefaultEmailTemplateType
+from .get_default_email_templates_response_200 import GetDefaultEmailTemplatesResponse200
+from .get_email_template_type import GetEmailTemplateType
+from .get_o_auth_config_provider import GetOAuthConfigProvider
+from .get_o_auth_provider_token_provider import GetOAuthProviderTokenProvider
+from .get_o_auth_provider_token_response_200 import GetOAuthProviderTokenResponse200
+from .get_project_config_format import GetProjectConfigFormat
+from .git_connect_start_response import GitConnectStartResponse
+from .git_connection import GitConnection
+from .git_connections_response import GitConnectionsResponse
+from .git_installation import GitInstallation
+from .git_installations_response import GitInstallationsResponse
+from .git_repositories_response import GitRepositoriesResponse
+from .git_repository import GitRepository
+from .hosted_auth_page_type import HostedAuthPageType
+from .hosted_login_email_check_request import HostedLoginEmailCheckRequest
+from .hosted_login_email_check_response import HostedLoginEmailCheckResponse
+from .hosted_login_options_response import HostedLoginOptionsResponse
+from .hosted_renderable_page_type import HostedRenderablePageType
+from .import_connect_start_response import ImportConnectStartResponse
+from .import_connection import ImportConnection
+from .import_connections_response import ImportConnectionsResponse
+from .import_provider import ImportProvider
+from .import_source import ImportSource
+from .import_sources_response import ImportSourcesResponse
+from .list_anon_keys_response_200 import ListAnonKeysResponse200
+from .list_auth_users_status import ListAuthUsersStatus
+from .list_available_o_auth_providers_response_200 import ListAvailableOAuthProvidersResponse200
+from .list_available_o_auth_providers_response_200_providers_item import ListAvailableOAuthProvidersResponse200ProvidersItem
+from .list_database_regions_response_200_item import ListDatabaseRegionsResponse200Item
+from .list_deployments_operation import ListDeploymentsOperation
+from .list_deployments_order import ListDeploymentsOrder
+from .list_deployments_resource_type import ListDeploymentsResourceType
+from .list_deployments_status import ListDeploymentsStatus
+from .list_email_templates_response_200 import ListEmailTemplatesResponse200
+from .list_o_auth_configs_response_200 import ListOAuthConfigsResponse200
+from .list_postgres_versions_response_200_item import ListPostgresVersionsResponse200Item
+from .list_project_deployments_resource_type import ListProjectDeploymentsResourceType
+from .list_storage_objects_admin_response_200 import ListStorageObjectsAdminResponse200
+from .list_user_sessions_response_200 import ListUserSessionsResponse200
+from .list_user_sessions_sort import ListUserSessionsSort
+from .list_user_sessions_status import ListUserSessionsStatus
+from .live_log_level import LiveLogLevel
+from .log_activity_bucket import LogActivityBucket
+from .log_activity_bucket_counts import LogActivityBucketCounts
+from .log_activity_bucket_counts_levels import LogActivityBucketCountsLevels
+from .log_activity_bucket_counts_regions import LogActivityBucketCountsRegions
+from .log_activity_bucket_counts_resource_ids import LogActivityBucketCountsResourceIds
+from .log_activity_request import LogActivityRequest
+from .log_activity_response import LogActivityResponse
+from .log_database_request_resource import LogDatabaseRequestResource
+from .log_database_request_resource_type import LogDatabaseRequestResourceType
+from .log_deployment import LogDeployment
+from .log_deployment_request_selector import LogDeploymentRequestSelector
+from .log_deployment_stage import LogDeploymentStage
+from .log_event import LogEvent
+from .log_event_body_type_1 import LogEventBodyType1
+from .log_frontend_request_resource import LogFrontendRequestResource
+from .log_frontend_request_resource_type import LogFrontendRequestResourceType
+from .log_function_request_resource import LogFunctionRequestResource
+from .log_function_request_resource_type import LogFunctionRequestResourceType
+from .log_resource import LogResource
+from .log_resource_type import LogResourceType
+from .log_search_event import LogSearchEvent
+from .log_search_request import LogSearchRequest
+from .log_search_response import LogSearchResponse
+from .log_stream_request import LogStreamRequest
+from .metric_usage_data import MetricUsageData
+from .o_auth_config import OAuthConfig
+from .o_auth_config_provider import OAuthConfigProvider
+from .o_auth_error_response import OAuthErrorResponse
+from .paginated_auth_users import PaginatedAuthUsers
+from .paginated_databases import PaginatedDatabases
+from .paginated_frontend_deployments import PaginatedFrontendDeployments
+from .paginated_frontends import PaginatedFrontends
+from .paginated_function_deployments import PaginatedFunctionDeployments
+from .paginated_functions import PaginatedFunctions
+from .paginated_project_custom_domains import PaginatedProjectCustomDomains
+from .paginated_project_deployments import PaginatedProjectDeployments
+from .paginated_projects import PaginatedProjects
+from .paginated_projects_status import PaginatedProjectsStatus
+from .paginated_service_keys import PaginatedServiceKeys
+from .paginated_storage_buckets import PaginatedStorageBuckets
+from .paginated_variables import PaginatedVariables
+from .platform_exchange_response import PlatformExchangeResponse
+from .project import Project
+from .project_config import ProjectConfig
+from .project_config_apply_result import ProjectConfigApplyResult
+from .project_config_apply_result_entry import ProjectConfigApplyResultEntry
+from .project_config_apply_result_entry_action import ProjectConfigApplyResultEntryAction
+from .project_config_apply_summary import ProjectConfigApplySummary
+from .project_config_auth import ProjectConfigAuth
+from .project_config_auth_cors import ProjectConfigAuthCORS
+from .project_config_auth_email import ProjectConfigAuthEmail
+from .project_config_auth_email_from import ProjectConfigAuthEmailFrom
+from .project_config_auth_email_password_provider import ProjectConfigAuthEmailPasswordProvider
+from .project_config_auth_email_smtp import ProjectConfigAuthEmailSMTP
+from .project_config_auth_email_verification import ProjectConfigAuthEmailVerification
+from .project_config_auth_managed_pages import ProjectConfigAuthManagedPages
+from .project_config_auth_password import ProjectConfigAuthPassword
+from .project_config_auth_password_reset import ProjectConfigAuthPasswordReset
+from .project_config_auth_providers import ProjectConfigAuthProviders
+from .project_config_auth_rate_limits import ProjectConfigAuthRateLimits
+from .project_config_auth_redirects import ProjectConfigAuthRedirects
+from .project_config_auth_sessions import ProjectConfigAuthSessions
+from .project_config_auth_signup import ProjectConfigAuthSignup
+from .project_config_auth_signup_allowed_email_domains_mode import ProjectConfigAuthSignupAllowedEmailDomainsMode
+from .project_config_auth_tokens import ProjectConfigAuthTokens
+from .project_config_bucket import ProjectConfigBucket
+from .project_config_bucket_policy import ProjectConfigBucketPolicy
+from .project_config_bucket_policy_operation import ProjectConfigBucketPolicyOperation
+from .project_config_custom_domain import ProjectConfigCustomDomain
+from .project_config_database import ProjectConfigDatabase
+from .project_config_database_database_type import ProjectConfigDatabaseDatabaseType
+from .project_config_database_pg_version import ProjectConfigDatabasePgVersion
+from .project_config_email_template import ProjectConfigEmailTemplate
+from .project_config_email_templates import ProjectConfigEmailTemplates
+from .project_config_frontend import ProjectConfigFrontend
+from .project_config_function import ProjectConfigFunction
+from .project_config_hosted_page import ProjectConfigHostedPage
+from .project_config_hosted_pages import ProjectConfigHostedPages
+from .project_config_missing_resource import ProjectConfigMissingResource
+from .project_config_missing_resource_type import ProjectConfigMissingResourceType
+from .project_config_o_auth_provider import ProjectConfigOAuthProvider
+from .project_config_o_auth_provider_provider import ProjectConfigOAuthProviderProvider
+from .project_config_project import ProjectConfigProject
+from .project_config_realtime import ProjectConfigRealtime
+from .project_config_scheduler import ProjectConfigScheduler
+from .project_config_scheduler_payload import ProjectConfigSchedulerPayload
+from .project_config_skipped_resource import ProjectConfigSkippedResource
+from .project_config_skipped_resource_type import ProjectConfigSkippedResourceType
+from .project_config_validation_error import ProjectConfigValidationError
+from .project_config_validation_error_response import ProjectConfigValidationErrorResponse
+from .project_config_variable import ProjectConfigVariable
+from .project_config_version import ProjectConfigVersion
+from .project_deployment import ProjectDeployment
+from .project_deployment_deploy_source import ProjectDeploymentDeploySource
+from .project_deployment_operation import ProjectDeploymentOperation
+from .project_deployment_resource import ProjectDeploymentResource
+from .project_deployment_resource_type import ProjectDeploymentResourceType
+from .project_deployment_status import ProjectDeploymentStatus
+from .project_deployment_summary import ProjectDeploymentSummary
+from .project_frontend_custom_domain import ProjectFrontendCustomDomain
+from .project_frontend_custom_domain_frontend import ProjectFrontendCustomDomainFrontend
+from .project_git_connection import ProjectGitConnection
+from .project_git_deploy_settings import ProjectGitDeploySettings
+from .project_health_category import ProjectHealthCategory
+from .project_health_check import ProjectHealthCheck
+from .project_health_data_status import ProjectHealthDataStatus
+from .project_health_evidence import ProjectHealthEvidence
+from .project_health_resource import ProjectHealthResource
+from .project_health_resource_type import ProjectHealthResourceType
+from .project_health_response import ProjectHealthResponse
+from .project_health_scope import ProjectHealthScope
+from .project_health_status import ProjectHealthStatus
+from .project_import_action import ProjectImportAction
+from .project_import_action_code import ProjectImportActionCode
+from .project_import_destination import ProjectImportDestination
+from .project_import_destination_mode import ProjectImportDestinationMode
+from .project_import_disposition import ProjectImportDisposition
+from .project_import_finding import ProjectImportFinding
+from .project_import_impact import ProjectImportImpact
+from .project_import_preflight_request import ProjectImportPreflightRequest
+from .project_import_readiness import ProjectImportReadiness
+from .project_import_report import ProjectImportReport
+from .project_import_resource import ProjectImportResource
+from .project_import_resource_kind import ProjectImportResourceKind
+from .project_import_run import ProjectImportRun
+from .project_import_run_status import ProjectImportRunStatus
+from .project_import_start_request import ProjectImportStartRequest
+from .project_import_summary import ProjectImportSummary
+from .project_import_target import ProjectImportTarget
+from .project_lock_lease import ProjectLockLease
+from .project_lock_lease_request import ProjectLockLeaseRequest
+from .project_lock_state import ProjectLockState
+from .project_metrics_data_status import ProjectMetricsDataStatus
+from .project_metrics_dimensions import ProjectMetricsDimensions
+from .project_metrics_dimensions_resource_type import ProjectMetricsDimensionsResourceType
+from .project_metrics_group_by import ProjectMetricsGroupBy
+from .project_metrics_metric import ProjectMetricsMetric
+from .project_metrics_query import ProjectMetricsQuery
+from .project_metrics_query_request import ProjectMetricsQueryRequest
+from .project_metrics_query_response import ProjectMetricsQueryResponse
+from .project_metrics_query_time_range import ProjectMetricsQueryTimeRange
+from .project_metrics_query_time_range_window import ProjectMetricsQueryTimeRangeWindow
+from .project_metrics_result import ProjectMetricsResult
+from .project_metrics_unit import ProjectMetricsUnit
+from .project_metrics_value import ProjectMetricsValue
+from .project_metrics_window import ProjectMetricsWindow
+from .project_plan import ProjectPlan
+from .project_status import ProjectStatus
+from .project_usage_response import ProjectUsageResponse
+from .realtime_config import RealtimeConfig
+from .realtime_plan_limits import RealtimePlanLimits
+from .realtime_stats import RealtimeStats
+from .refresh_o_auth_provider_token_provider import RefreshOAuthProviderTokenProvider
+from .refresh_o_auth_provider_token_response_200 import RefreshOAuthProviderTokenResponse200
+from .render_default_managed_auth_page_action import RenderDefaultManagedAuthPageAction
+from .reset_database_password_response_200 import ResetDatabasePasswordResponse200
+from .resolve_function_response import ResolveFunctionResponse
+from .resource_reference import ResourceReference
+from .resource_reference_type import ResourceReferenceType
+from .schedule_request import ScheduleRequest
+from .schedule_request_kind import ScheduleRequestKind
+from .service_key import ServiceKey
+from .set_project_git_production_branch_request import SetProjectGitProductionBranchRequest
+from .start_git_connect_provider import StartGitConnectProvider
+from .storage_bucket import StorageBucket
+from .storage_copy_request import StorageCopyRequest
+from .storage_list_response import StorageListResponse
+from .storage_move_request import StorageMoveRequest
+from .storage_object import StorageObject
+from .storage_object_metadata import StorageObjectMetadata
+from .storage_object_with_bucket import StorageObjectWithBucket
+from .storage_object_with_bucket_metadata import StorageObjectWithBucketMetadata
+from .storage_policy import StoragePolicy
+from .storage_policy_operation import StoragePolicyOperation
+from .storage_stats import StorageStats
+from .storage_visibility_request import StorageVisibilityRequest
+from .summarize_project_deployments_resource_type import SummarizeProjectDeploymentsResourceType
+from .test_email_request import TestEmailRequest
+from .test_email_response import TestEmailResponse
+from .unban_user_response import UnbanUserResponse
+from .unban_user_response_status import UnbanUserResponseStatus
+from .update_auth_config_request import UpdateAuthConfigRequest
+from .update_auth_config_request_allowed_email_domains_mode import UpdateAuthConfigRequestAllowedEmailDomainsMode
+from .update_auth_hosted_page_request import UpdateAuthHostedPageRequest
+from .update_database_branch_request import UpdateDatabaseBranchRequest
+from .update_database_type_request import UpdateDatabaseTypeRequest
+from .update_database_type_request_database_type import UpdateDatabaseTypeRequestDatabaseType
+from .update_email_template_request import UpdateEmailTemplateRequest
+from .update_email_template_type import UpdateEmailTemplateType
+from .update_function_request import UpdateFunctionRequest
+from .update_function_scheduler_request import UpdateFunctionSchedulerRequest
+from .update_function_scheduler_request_payload import UpdateFunctionSchedulerRequestPayload
+from .update_o_auth_config_provider import UpdateOAuthConfigProvider
+from .update_o_auth_config_request import UpdateOAuthConfigRequest
+from .update_project_git_deploy_settings_request import UpdateProjectGitDeploySettingsRequest
+from .update_project_request import UpdateProjectRequest
+from .update_realtime_config_request import UpdateRealtimeConfigRequest
+from .update_storage_bucket_request import UpdateStorageBucketRequest
+from .update_variable_request import UpdateVariableRequest
+from .upload_project_logo_body import UploadProjectLogoBody
+from .upload_session_part import UploadSessionPart
+from .upload_session_status_response import UploadSessionStatusResponse
+from .upload_session_status_response_status import UploadSessionStatusResponseStatus
+from .upload_storage_object_files_body import UploadStorageObjectFilesBody
+from .upload_storage_object_x_upload_complete import UploadStorageObjectXUploadComplete
+from .usage_data_point import UsageDataPoint
+from .variable import Variable
+from .variable_deploy_source import VariableDeploySource
+from .variable_status import VariableStatus
+
+__all__ = (
+ "AnonKey",
+ "AuthCancelEmailChangeResponse200",
+ "AuthConfig",
+ "AuthConfigAllowedEmailDomainsMode",
+ "AuthConfirmEmailBody",
+ "AuthConfirmEmailChangeBody",
+ "AuthConfirmEmailChangeResponse200",
+ "AuthConfirmEmailResponse200",
+ "AuthConfirmEmailResponse200Message",
+ "AuthConvertAnonymousBody",
+ "AuthConvertAnonymousBodyUserMetadata",
+ "AuthConvertAnonymousResponse200",
+ "AuthDeviceAuthorizeBody",
+ "AuthDeviceTokenBody",
+ "AuthDeviceTokenBodyGrantType",
+ "AuthDeviceVerifyBody",
+ "AuthDeviceVerifyBodyAction",
+ "AuthDeviceVerifyResponse200",
+ "AuthForgotPasswordBody",
+ "AuthForgotPasswordResponse200",
+ "AuthGetMySessionsResponse200",
+ "AuthGetMySessionsSort",
+ "AuthGetMySessionsStatus",
+ "AuthGetUserResponse200",
+ "AuthHostedPage",
+ "AuthHostedPageDefaults",
+ "AuthHostedPageResponse",
+ "AuthHostedPageRuntime",
+ "AuthIdentitiesResponse",
+ "AuthIdentity",
+ "AuthInsightsInterval",
+ "AuthInsightsResponse",
+ "AuthInsightsSeriesPoint",
+ "AuthInsightsSummary",
+ "AuthInsightsWindow",
+ "AuthLinkOAuthProviderProvider",
+ "AuthLinkOAuthProviderResponse200",
+ "AuthLinkOAuthProviderResponseMode",
+ "AuthListOAuthProvidersResponse200",
+ "AuthListOAuthProvidersResponse200ProvidersItem",
+ "AuthLogoutBody",
+ "AuthLogoutBodySessionMode",
+ "AuthMethodsResponse",
+ "AuthMethodSummary",
+ "AuthMethodSummaryType",
+ "AuthOAuthAuthorizeProvider",
+ "AuthOAuthAuthorizeResponseMode",
+ "AuthOAuthCallbackProvider",
+ "AuthOAuthExchangeBody",
+ "AuthPasswordPolicy",
+ "AuthPlatformExchangeBody",
+ "AuthRefreshBody",
+ "AuthRefreshBodySessionMode",
+ "AuthRequestEmailChangeBody",
+ "AuthRequestEmailChangeResponse200",
+ "AuthResendConfirmationBody",
+ "AuthResendConfirmationResponse200",
+ "AuthResetPasswordBody",
+ "AuthResetPasswordResponse200",
+ "AuthSession",
+ "AuthSessionProvider",
+ "AuthSigninBody",
+ "AuthSigninBodySessionMode",
+ "AuthSignupAnonymousBody",
+ "AuthSignupAnonymousBodyUserMetadata",
+ "AuthSignupBody",
+ "AuthSignupBodyUserMetadata",
+ "AuthSignupResponse",
+ "AuthTokenResponse",
+ "AuthUnlinkOAuthProviderProvider",
+ "AuthUpdateUserBody",
+ "AuthUpdateUserBodyUserMetadata",
+ "AuthUpdateUserResponse200",
+ "AuthUser",
+ "AuthUserAppMetadata",
+ "AuthUserStatus",
+ "AuthUserUserMetadata",
+ "BanAuthUserBody",
+ "BanUserResponse",
+ "BanUserResponseStatus",
+ "BatchFunctionDeployFailure",
+ "BatchFunctionDeployFailureOperation",
+ "BatchFunctionDeployResponse",
+ "CallOAuthProviderAPIBody",
+ "CallOAuthProviderAPIBodyBody",
+ "CallOAuthProviderAPIBodyMethod",
+ "CallOAuthProviderAPIProvider",
+ "CallOAuthProviderAPIResponse200",
+ "CompleteUploadSessionResponse",
+ "ConfigureAuthMethodsBody",
+ "ConfigureAuthMethodsBodyOauthProvidersItem",
+ "ConnectProjectGitRequest",
+ "CreateAnonKeyBody",
+ "CreateAnonKeyBodyPermissionsItem",
+ "CreateDatabaseBranchRequest",
+ "CreateDatabaseRequest",
+ "CreateDatabaseRequestDatabaseType",
+ "CreateDatabaseRequestPgVersion",
+ "CreateDatabaseRequestRegion",
+ "CreateEmailTemplateRequest",
+ "CreateEmailTemplateRequestTemplateType",
+ "CreateFrontendBody",
+ "CreateFrontendBodyFramework",
+ "CreateFrontendCustomDomainRequest",
+ "CreateFunctionBody",
+ "CreateFunctionBodyRuntime",
+ "CreateFunctionsBatchBody",
+ "CreateFunctionSchedulerRequest",
+ "CreateFunctionSchedulerRequestPayload",
+ "CreateOAuthConfigRequest",
+ "CreateOAuthConfigRequestProvider",
+ "CreateProjectRequest",
+ "CreateServiceKeyBody",
+ "CreateStorageBucketRequest",
+ "CreateStoragePolicyRequest",
+ "CreateStoragePolicyRequestOperation",
+ "CreateUploadSessionRequest",
+ "CreateUploadSessionResponse",
+ "CreateVariableRequest",
+ "Database",
+ "DatabaseBranch",
+ "DatabaseBranchList",
+ "DatabaseBranchStatus",
+ "DatabaseBranchStorage",
+ "DatabaseDatabaseType",
+ "DatabaseDeleteRequest",
+ "DatabaseInsertRequest",
+ "DatabaseInsertRequestValues",
+ "DatabaseQueryFilter",
+ "DatabaseQueryFilterOperator",
+ "DatabaseQueryOrder",
+ "DatabaseQueryPerformanceDatabase",
+ "DatabaseQueryPerformanceItem",
+ "DatabaseQueryPerformanceResponse",
+ "DatabaseQueryResult",
+ "DatabaseQueryResultDataItem",
+ "DatabaseSelectRequest",
+ "DatabaseStats",
+ "DatabaseStatsGranularity",
+ "DatabaseStatus",
+ "DatabaseUpdateRequest",
+ "DatabaseUpdateRequestValues",
+ "DeleteDatabaseBranchResponse202",
+ "DeleteDatabaseResponse202",
+ "DeleteEmailTemplateType",
+ "DeleteOAuthConfigProvider",
+ "DeploymentPhase",
+ "DeploymentPhaseName",
+ "DeploymentPhaseStatus",
+ "DeploymentProgress",
+ "DeploymentProgressCurrentPhase",
+ "DeploymentReference",
+ "DeviceAuthorizationResponse",
+ "EmailTemplate",
+ "EmailTemplateTemplateType",
+ "Error",
+ "Frontend",
+ "FrontendCustomDomainResponse",
+ "FrontendCustomDomainResponseDomainStatus",
+ "FrontendCustomDomainResponseTlsMode",
+ "FrontendCustomDomainResponseVerificationStatus",
+ "FrontendCustomDomainStatus",
+ "FrontendCustomDomainTLSConfig",
+ "FrontendCustomDomainTLSConfigMode",
+ "FrontendDeployment",
+ "FrontendDeploymentDeploySource",
+ "FrontendDeploymentOperation",
+ "FrontendDeploymentStatus",
+ "FrontendDomainRoutingRecord",
+ "FrontendDomainRoutingRecordRecordType",
+ "FrontendDomainVerificationRecord",
+ "FrontendFramework",
+ "FrontendStatus",
+ "FrontendUsageDailyEntry",
+ "FrontendUsageData",
+ "FrontendUsageHistoryResponse",
+ "Function",
+ "FunctionDeployment",
+ "FunctionDeploymentDeploySource",
+ "FunctionDeploymentOperation",
+ "FunctionDeploymentStatus",
+ "FunctionInvocationRequest",
+ "FunctionInvocationRequestPayload",
+ "FunctionInvocationResponse",
+ "FunctionRegion",
+ "FunctionRuntimeDeployment",
+ "FunctionRuntimeOption",
+ "FunctionRuntimesResponse",
+ "FunctionScheduler",
+ "FunctionSchedulerListResponse",
+ "FunctionSchedulerPayload",
+ "FunctionSchedulerScheduleKind",
+ "FunctionStatus",
+ "GetAuthMethodsResponse200",
+ "GetAuthMethodsResponse200Anonymous",
+ "GetAuthMethodsResponse200EmailPassword",
+ "GetAuthMethodsResponse200OauthProvidersItem",
+ "GetDatabaseStatsGranularity",
+ "GetDefaultEmailTemplatesResponse200",
+ "GetDefaultEmailTemplateType",
+ "GetEmailTemplateType",
+ "GetOAuthConfigProvider",
+ "GetOAuthProviderTokenProvider",
+ "GetOAuthProviderTokenResponse200",
+ "GetProjectConfigFormat",
+ "GitConnection",
+ "GitConnectionsResponse",
+ "GitConnectStartResponse",
+ "GitInstallation",
+ "GitInstallationsResponse",
+ "GitRepositoriesResponse",
+ "GitRepository",
+ "HostedAuthPageType",
+ "HostedLoginEmailCheckRequest",
+ "HostedLoginEmailCheckResponse",
+ "HostedLoginOptionsResponse",
+ "HostedRenderablePageType",
+ "ImportConnection",
+ "ImportConnectionsResponse",
+ "ImportConnectStartResponse",
+ "ImportProvider",
+ "ImportSource",
+ "ImportSourcesResponse",
+ "ListAnonKeysResponse200",
+ "ListAuthUsersStatus",
+ "ListAvailableOAuthProvidersResponse200",
+ "ListAvailableOAuthProvidersResponse200ProvidersItem",
+ "ListDatabaseRegionsResponse200Item",
+ "ListDeploymentsOperation",
+ "ListDeploymentsOrder",
+ "ListDeploymentsResourceType",
+ "ListDeploymentsStatus",
+ "ListEmailTemplatesResponse200",
+ "ListOAuthConfigsResponse200",
+ "ListPostgresVersionsResponse200Item",
+ "ListProjectDeploymentsResourceType",
+ "ListStorageObjectsAdminResponse200",
+ "ListUserSessionsResponse200",
+ "ListUserSessionsSort",
+ "ListUserSessionsStatus",
+ "LiveLogLevel",
+ "LogActivityBucket",
+ "LogActivityBucketCounts",
+ "LogActivityBucketCountsLevels",
+ "LogActivityBucketCountsRegions",
+ "LogActivityBucketCountsResourceIds",
+ "LogActivityRequest",
+ "LogActivityResponse",
+ "LogDatabaseRequestResource",
+ "LogDatabaseRequestResourceType",
+ "LogDeployment",
+ "LogDeploymentRequestSelector",
+ "LogDeploymentStage",
+ "LogEvent",
+ "LogEventBodyType1",
+ "LogFrontendRequestResource",
+ "LogFrontendRequestResourceType",
+ "LogFunctionRequestResource",
+ "LogFunctionRequestResourceType",
+ "LogResource",
+ "LogResourceType",
+ "LogSearchEvent",
+ "LogSearchRequest",
+ "LogSearchResponse",
+ "LogStreamRequest",
+ "MetricUsageData",
+ "OAuthConfig",
+ "OAuthConfigProvider",
+ "OAuthErrorResponse",
+ "PaginatedAuthUsers",
+ "PaginatedDatabases",
+ "PaginatedFrontendDeployments",
+ "PaginatedFrontends",
+ "PaginatedFunctionDeployments",
+ "PaginatedFunctions",
+ "PaginatedProjectCustomDomains",
+ "PaginatedProjectDeployments",
+ "PaginatedProjects",
+ "PaginatedProjectsStatus",
+ "PaginatedServiceKeys",
+ "PaginatedStorageBuckets",
+ "PaginatedVariables",
+ "PlatformExchangeResponse",
+ "Project",
+ "ProjectConfig",
+ "ProjectConfigApplyResult",
+ "ProjectConfigApplyResultEntry",
+ "ProjectConfigApplyResultEntryAction",
+ "ProjectConfigApplySummary",
+ "ProjectConfigAuth",
+ "ProjectConfigAuthCORS",
+ "ProjectConfigAuthEmail",
+ "ProjectConfigAuthEmailFrom",
+ "ProjectConfigAuthEmailPasswordProvider",
+ "ProjectConfigAuthEmailSMTP",
+ "ProjectConfigAuthEmailVerification",
+ "ProjectConfigAuthManagedPages",
+ "ProjectConfigAuthPassword",
+ "ProjectConfigAuthPasswordReset",
+ "ProjectConfigAuthProviders",
+ "ProjectConfigAuthRateLimits",
+ "ProjectConfigAuthRedirects",
+ "ProjectConfigAuthSessions",
+ "ProjectConfigAuthSignup",
+ "ProjectConfigAuthSignupAllowedEmailDomainsMode",
+ "ProjectConfigAuthTokens",
+ "ProjectConfigBucket",
+ "ProjectConfigBucketPolicy",
+ "ProjectConfigBucketPolicyOperation",
+ "ProjectConfigCustomDomain",
+ "ProjectConfigDatabase",
+ "ProjectConfigDatabaseDatabaseType",
+ "ProjectConfigDatabasePgVersion",
+ "ProjectConfigEmailTemplate",
+ "ProjectConfigEmailTemplates",
+ "ProjectConfigFrontend",
+ "ProjectConfigFunction",
+ "ProjectConfigHostedPage",
+ "ProjectConfigHostedPages",
+ "ProjectConfigMissingResource",
+ "ProjectConfigMissingResourceType",
+ "ProjectConfigOAuthProvider",
+ "ProjectConfigOAuthProviderProvider",
+ "ProjectConfigProject",
+ "ProjectConfigRealtime",
+ "ProjectConfigScheduler",
+ "ProjectConfigSchedulerPayload",
+ "ProjectConfigSkippedResource",
+ "ProjectConfigSkippedResourceType",
+ "ProjectConfigValidationError",
+ "ProjectConfigValidationErrorResponse",
+ "ProjectConfigVariable",
+ "ProjectConfigVersion",
+ "ProjectDeployment",
+ "ProjectDeploymentDeploySource",
+ "ProjectDeploymentOperation",
+ "ProjectDeploymentResource",
+ "ProjectDeploymentResourceType",
+ "ProjectDeploymentStatus",
+ "ProjectDeploymentSummary",
+ "ProjectFrontendCustomDomain",
+ "ProjectFrontendCustomDomainFrontend",
+ "ProjectGitConnection",
+ "ProjectGitDeploySettings",
+ "ProjectHealthCategory",
+ "ProjectHealthCheck",
+ "ProjectHealthDataStatus",
+ "ProjectHealthEvidence",
+ "ProjectHealthResource",
+ "ProjectHealthResourceType",
+ "ProjectHealthResponse",
+ "ProjectHealthScope",
+ "ProjectHealthStatus",
+ "ProjectImportAction",
+ "ProjectImportActionCode",
+ "ProjectImportDestination",
+ "ProjectImportDestinationMode",
+ "ProjectImportDisposition",
+ "ProjectImportFinding",
+ "ProjectImportImpact",
+ "ProjectImportPreflightRequest",
+ "ProjectImportReadiness",
+ "ProjectImportReport",
+ "ProjectImportResource",
+ "ProjectImportResourceKind",
+ "ProjectImportRun",
+ "ProjectImportRunStatus",
+ "ProjectImportStartRequest",
+ "ProjectImportSummary",
+ "ProjectImportTarget",
+ "ProjectLockLease",
+ "ProjectLockLeaseRequest",
+ "ProjectLockState",
+ "ProjectMetricsDataStatus",
+ "ProjectMetricsDimensions",
+ "ProjectMetricsDimensionsResourceType",
+ "ProjectMetricsGroupBy",
+ "ProjectMetricsMetric",
+ "ProjectMetricsQuery",
+ "ProjectMetricsQueryRequest",
+ "ProjectMetricsQueryResponse",
+ "ProjectMetricsQueryTimeRange",
+ "ProjectMetricsQueryTimeRangeWindow",
+ "ProjectMetricsResult",
+ "ProjectMetricsUnit",
+ "ProjectMetricsValue",
+ "ProjectMetricsWindow",
+ "ProjectPlan",
+ "ProjectStatus",
+ "ProjectUsageResponse",
+ "RealtimeConfig",
+ "RealtimePlanLimits",
+ "RealtimeStats",
+ "RefreshOAuthProviderTokenProvider",
+ "RefreshOAuthProviderTokenResponse200",
+ "RenderDefaultManagedAuthPageAction",
+ "ResetDatabasePasswordResponse200",
+ "ResolveFunctionResponse",
+ "ResourceReference",
+ "ResourceReferenceType",
+ "ScheduleRequest",
+ "ScheduleRequestKind",
+ "ServiceKey",
+ "SetProjectGitProductionBranchRequest",
+ "StartGitConnectProvider",
+ "StorageBucket",
+ "StorageCopyRequest",
+ "StorageListResponse",
+ "StorageMoveRequest",
+ "StorageObject",
+ "StorageObjectMetadata",
+ "StorageObjectWithBucket",
+ "StorageObjectWithBucketMetadata",
+ "StoragePolicy",
+ "StoragePolicyOperation",
+ "StorageStats",
+ "StorageVisibilityRequest",
+ "SummarizeProjectDeploymentsResourceType",
+ "TestEmailRequest",
+ "TestEmailResponse",
+ "UnbanUserResponse",
+ "UnbanUserResponseStatus",
+ "UpdateAuthConfigRequest",
+ "UpdateAuthConfigRequestAllowedEmailDomainsMode",
+ "UpdateAuthHostedPageRequest",
+ "UpdateDatabaseBranchRequest",
+ "UpdateDatabaseTypeRequest",
+ "UpdateDatabaseTypeRequestDatabaseType",
+ "UpdateEmailTemplateRequest",
+ "UpdateEmailTemplateType",
+ "UpdateFunctionRequest",
+ "UpdateFunctionSchedulerRequest",
+ "UpdateFunctionSchedulerRequestPayload",
+ "UpdateOAuthConfigProvider",
+ "UpdateOAuthConfigRequest",
+ "UpdateProjectGitDeploySettingsRequest",
+ "UpdateProjectRequest",
+ "UpdateRealtimeConfigRequest",
+ "UpdateStorageBucketRequest",
+ "UpdateVariableRequest",
+ "UploadProjectLogoBody",
+ "UploadSessionPart",
+ "UploadSessionStatusResponse",
+ "UploadSessionStatusResponseStatus",
+ "UploadStorageObjectFilesBody",
+ "UploadStorageObjectXUploadComplete",
+ "UsageDataPoint",
+ "Variable",
+ "VariableDeploySource",
+ "VariableStatus",
+)
diff --git a/src/volcano_sdk/_generated/models/anon_key.py b/src/volcano_sdk/_generated/models/anon_key.py
new file mode 100644
index 00000000..3658b070
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/anon_key.py
@@ -0,0 +1,167 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AnonKey")
+
+
+
+@_attrs_define
+class AnonKey:
+ """
+ Attributes:
+ id (UUID):
+ name (str):
+ key_value (str): JWT token - use this in frontend Authorization header
+ project_id (UUID | Unset):
+ permissions (list[str] | Unset): Permissions granted to this anon key.
+ Auth permissions: auth.signup, auth.signin, auth.refresh, auth.logout, auth.password_reset, auth.confirm_email,
+ auth.resend_confirmation
+ Storage permissions: storage.upload, storage.download, storage.list, storage.delete
+ Realtime permissions: realtime.connect, realtime.subscribe, realtime.publish
+ Functions permissions: functions.invoke
+ Example: ['auth.signup', 'auth.signin', 'auth.refresh', 'auth.logout'].
+ is_default (bool | Unset): Whether this is the project's configured default anon key. Only one key per project
+ can be default.
+ created_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ name: str
+ key_value: str
+ project_id: UUID | Unset = UNSET
+ permissions: list[str] | Unset = UNSET
+ is_default: bool | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ name = self.name
+
+ key_value = self.key_value
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ permissions: list[str] | Unset = UNSET
+ if not isinstance(self.permissions, Unset):
+ permissions = self.permissions
+
+
+
+ is_default = self.is_default
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ "key_value": key_value,
+ })
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if permissions is not UNSET:
+ field_dict["permissions"] = permissions
+ if is_default is not UNSET:
+ field_dict["is_default"] = is_default
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ key_value = d.pop("key_value")
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ permissions = cast(list[str], d.pop("permissions", UNSET))
+
+
+ is_default = d.pop("is_default", UNSET)
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ anon_key = cls(
+ id=id,
+ name=name,
+ key_value=key_value,
+ project_id=project_id,
+ permissions=permissions,
+ is_default=is_default,
+ created_at=created_at,
+ )
+
+
+ anon_key.additional_properties = d
+ return anon_key
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_cancel_email_change_response_200.py b/src/volcano_sdk/_generated/models/auth_cancel_email_change_response_200.py
new file mode 100644
index 00000000..801923a7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_cancel_email_change_response_200.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthCancelEmailChangeResponse200")
+
+
+
+@_attrs_define
+class AuthCancelEmailChangeResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ """
+
+ message: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ auth_cancel_email_change_response_200 = cls(
+ message=message,
+ )
+
+
+ auth_cancel_email_change_response_200.additional_properties = d
+ return auth_cancel_email_change_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_config.py b/src/volcano_sdk/_generated/models/auth_config.py
new file mode 100644
index 00000000..34482b5b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_config.py
@@ -0,0 +1,559 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_config_allowed_email_domains_mode import AuthConfigAllowedEmailDomainsMode
+from ..models.auth_config_allowed_email_domains_mode import check_auth_config_allowed_email_domains_mode
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+if TYPE_CHECKING:
+ from ..models.auth_password_policy import AuthPasswordPolicy
+
+
+
+
+
+T = TypeVar("T", bound="AuthConfig")
+
+
+
+@_attrs_define
+class AuthConfig:
+ """
+ Attributes:
+ password_policy (AuthPasswordPolicy): Effective backend-enforced password policy.
+ project_id (UUID | Unset):
+ access_token_lifetime (int | Unset): Access token lifetime in seconds Default: 3600.
+ refresh_token_lifetime (int | Unset): Refresh token lifetime in seconds Default: 2592000.
+ inactivity_timeout (int | Unset): Force re-login after inactivity (seconds, 0=never) Default: 0.
+ max_session_duration (int | Unset): Force re-login after duration (seconds, 0=never) Default: 0.
+ min_password_length (int | Unset): Configured minimum password length in Unicode characters. Default: 15.
+ require_uppercase (bool | Unset): Default: False.
+ require_lowercase (bool | Unset): Default: False.
+ require_numbers (bool | Unset): Default: False.
+ require_special_chars (bool | Unset): Default: False.
+ enable_signup (bool | Unset): Master switch - allow new user signups via ANY provider Default: True.
+ enable_email_password (bool | Unset): Enable email/password authentication as a provider Default: True.
+ rate_limit_signup (int | Unset): Signups per hour per IP Default: 100.
+ rate_limit_signin (int | Unset): Signins per hour per IP Default: 100.
+ rate_limit_token_refresh (int | Unset): Refreshes per hour per IP Default: 1000.
+ cors_enabled (bool | Unset): Default: False.
+ cors_allowed_origins (list[str] | Unset): Example: ['https://myapp.com', 'http://localhost:3000'].
+ enable_anonymous_signins (bool | Unset): Allow creating users without email/password Default: False.
+ allowed_email_domains (list[str] | Unset): Email domains allowed to create users in this project. Applies to
+ email/password signup, OAuth/SSO signup, anonymous conversion, and
+ email changes. Empty (the default) allows every domain.
+
+ Entries are stored normalized (lowercase, no `@` prefix) and match
+ the domain part exactly: `domain1.com` does not cover
+ `mail.domain1.com`. Signups from other domains are rejected with
+ 403, and `allowed_email_domains_mode` decides whether sign-in is
+ covered as well.
+
+ The allowlist is a PRO feature to configure and to enforce. A
+ downgrade parks it: the domains are still returned here and stop
+ being applied until the project is back on PRO.
+ Example: ['domain1.com', 'domain2.com'].
+ allowed_email_domains_mode (AuthConfigAllowedEmailDomainsMode | Unset): How far `allowed_email_domains` reaches.
+ `signup` only gates account
+ creation, so accounts that predate the list keep signing in.
+ `signup_and_signin` also refuses to issue a session to an account
+ whose domain is not listed. `disabled` keeps the list without
+ enforcing it.
+ Default: 'signup'.
+ platform_token_ttl (int | Unset): TTL in seconds for platform tokens minted via `/auth/platform/exchange`
+ Default: 2592000.
+ allow_password_reset (bool | Unset): Enable forgot password flow Default: True.
+ password_reset_timeout (int | Unset): Recovery token expiry in seconds Default: 3600.
+ max_password_history (int | Unset): Number of previous passwords to remember (0=disabled) Default: 0.
+ cors_allow_credentials (bool | Unset): Allow credentials in CORS requests Default: True.
+ cors_max_age (int | Unset): CORS preflight cache duration (seconds) Default: 86400.
+ require_email_confirmation (bool | Unset): Require users to confirm email before sign-in. Can only be true when
+ email_enabled is true. Default: False.
+ email_confirmation_timeout (int | Unset): Email confirmation token expiry in seconds. Default: 86400.
+ auto_link_verified_oauth (bool | Unset): Link a verified OAuth identity to an existing confirmed account with
+ the same email instead of returning a conflict. Requires require_email_confirmation to be true. Default: False.
+ email_enabled (bool | Unset): Enable transactional email sending (confirmation, reset, change notifications).
+ Must be true when require_email_confirmation is true. Default: False.
+ email_from_address (str | Unset):
+ email_from_name (str | Unset):
+ smtp_host (str | Unset):
+ smtp_port (int | Unset): Default: 587.
+ smtp_username (str | Unset):
+ smtp_password_configured (bool | Unset): Whether an SMTP password is configured. The password itself is never
+ returned. Default: False.
+ smtp_use_tls (bool | Unset): Default: True.
+ email_confirmation_subject (str | Unset):
+ email_password_reset_subject (str | Unset):
+ email_password_changed_subject (str | Unset):
+ managed_auth_enabled (bool | Unset): Enables project-hosted managed auth pages. Default: False.
+ post_auth_redirect_url (str | Unset): Default redirect target after successful hosted auth.
+ allowed_redirect_urls (list[str] | Unset): Redirect allowlist used to validate post_auth_redirect_url and
+ post_logout_redirect_url.
+ post_logout_redirect_url (str | Unset): Redirect target after logout from hosted pages.
+ device_verification_url (str | Unset): Optional override for the device-authorization verification page.
+ When set, POST /auth/device/authorize returns this URL (with the
+ user_code) as verification_uri/verification_uri_complete instead of
+ the built-in managed device page. Lets a CLI surface the project's
+ own RFC 8628 approval page. Empty falls back to the managed page.
+ Example: https://app.acme.com/device.
+ """
+
+ password_policy: AuthPasswordPolicy
+ project_id: UUID | Unset = UNSET
+ access_token_lifetime: int | Unset = 3600
+ refresh_token_lifetime: int | Unset = 2592000
+ inactivity_timeout: int | Unset = 0
+ max_session_duration: int | Unset = 0
+ min_password_length: int | Unset = 15
+ require_uppercase: bool | Unset = False
+ require_lowercase: bool | Unset = False
+ require_numbers: bool | Unset = False
+ require_special_chars: bool | Unset = False
+ enable_signup: bool | Unset = True
+ enable_email_password: bool | Unset = True
+ rate_limit_signup: int | Unset = 100
+ rate_limit_signin: int | Unset = 100
+ rate_limit_token_refresh: int | Unset = 1000
+ cors_enabled: bool | Unset = False
+ cors_allowed_origins: list[str] | Unset = UNSET
+ enable_anonymous_signins: bool | Unset = False
+ allowed_email_domains: list[str] | Unset = UNSET
+ allowed_email_domains_mode: AuthConfigAllowedEmailDomainsMode | Unset = 'signup'
+ platform_token_ttl: int | Unset = 2592000
+ allow_password_reset: bool | Unset = True
+ password_reset_timeout: int | Unset = 3600
+ max_password_history: int | Unset = 0
+ cors_allow_credentials: bool | Unset = True
+ cors_max_age: int | Unset = 86400
+ require_email_confirmation: bool | Unset = False
+ email_confirmation_timeout: int | Unset = 86400
+ auto_link_verified_oauth: bool | Unset = False
+ email_enabled: bool | Unset = False
+ email_from_address: str | Unset = UNSET
+ email_from_name: str | Unset = UNSET
+ smtp_host: str | Unset = UNSET
+ smtp_port: int | Unset = 587
+ smtp_username: str | Unset = UNSET
+ smtp_password_configured: bool | Unset = False
+ smtp_use_tls: bool | Unset = True
+ email_confirmation_subject: str | Unset = UNSET
+ email_password_reset_subject: str | Unset = UNSET
+ email_password_changed_subject: str | Unset = UNSET
+ managed_auth_enabled: bool | Unset = False
+ post_auth_redirect_url: str | Unset = UNSET
+ allowed_redirect_urls: list[str] | Unset = UNSET
+ post_logout_redirect_url: str | Unset = UNSET
+ device_verification_url: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_password_policy import AuthPasswordPolicy
+ password_policy = self.password_policy.to_dict()
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ access_token_lifetime = self.access_token_lifetime
+
+ refresh_token_lifetime = self.refresh_token_lifetime
+
+ inactivity_timeout = self.inactivity_timeout
+
+ max_session_duration = self.max_session_duration
+
+ min_password_length = self.min_password_length
+
+ require_uppercase = self.require_uppercase
+
+ require_lowercase = self.require_lowercase
+
+ require_numbers = self.require_numbers
+
+ require_special_chars = self.require_special_chars
+
+ enable_signup = self.enable_signup
+
+ enable_email_password = self.enable_email_password
+
+ rate_limit_signup = self.rate_limit_signup
+
+ rate_limit_signin = self.rate_limit_signin
+
+ rate_limit_token_refresh = self.rate_limit_token_refresh
+
+ cors_enabled = self.cors_enabled
+
+ cors_allowed_origins: list[str] | Unset = UNSET
+ if not isinstance(self.cors_allowed_origins, Unset):
+ cors_allowed_origins = self.cors_allowed_origins
+
+
+
+ enable_anonymous_signins = self.enable_anonymous_signins
+
+ allowed_email_domains: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_email_domains, Unset):
+ allowed_email_domains = self.allowed_email_domains
+
+
+
+ allowed_email_domains_mode: str | Unset = UNSET
+ if not isinstance(self.allowed_email_domains_mode, Unset):
+ allowed_email_domains_mode = self.allowed_email_domains_mode
+
+
+ platform_token_ttl = self.platform_token_ttl
+
+ allow_password_reset = self.allow_password_reset
+
+ password_reset_timeout = self.password_reset_timeout
+
+ max_password_history = self.max_password_history
+
+ cors_allow_credentials = self.cors_allow_credentials
+
+ cors_max_age = self.cors_max_age
+
+ require_email_confirmation = self.require_email_confirmation
+
+ email_confirmation_timeout = self.email_confirmation_timeout
+
+ auto_link_verified_oauth = self.auto_link_verified_oauth
+
+ email_enabled = self.email_enabled
+
+ email_from_address = self.email_from_address
+
+ email_from_name = self.email_from_name
+
+ smtp_host = self.smtp_host
+
+ smtp_port = self.smtp_port
+
+ smtp_username = self.smtp_username
+
+ smtp_password_configured = self.smtp_password_configured
+
+ smtp_use_tls = self.smtp_use_tls
+
+ email_confirmation_subject = self.email_confirmation_subject
+
+ email_password_reset_subject = self.email_password_reset_subject
+
+ email_password_changed_subject = self.email_password_changed_subject
+
+ managed_auth_enabled = self.managed_auth_enabled
+
+ post_auth_redirect_url = self.post_auth_redirect_url
+
+ allowed_redirect_urls: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_redirect_urls, Unset):
+ allowed_redirect_urls = self.allowed_redirect_urls
+
+
+
+ post_logout_redirect_url = self.post_logout_redirect_url
+
+ device_verification_url = self.device_verification_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "password_policy": password_policy,
+ })
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if access_token_lifetime is not UNSET:
+ field_dict["access_token_lifetime"] = access_token_lifetime
+ if refresh_token_lifetime is not UNSET:
+ field_dict["refresh_token_lifetime"] = refresh_token_lifetime
+ if inactivity_timeout is not UNSET:
+ field_dict["inactivity_timeout"] = inactivity_timeout
+ if max_session_duration is not UNSET:
+ field_dict["max_session_duration"] = max_session_duration
+ if min_password_length is not UNSET:
+ field_dict["min_password_length"] = min_password_length
+ if require_uppercase is not UNSET:
+ field_dict["require_uppercase"] = require_uppercase
+ if require_lowercase is not UNSET:
+ field_dict["require_lowercase"] = require_lowercase
+ if require_numbers is not UNSET:
+ field_dict["require_numbers"] = require_numbers
+ if require_special_chars is not UNSET:
+ field_dict["require_special_chars"] = require_special_chars
+ if enable_signup is not UNSET:
+ field_dict["enable_signup"] = enable_signup
+ if enable_email_password is not UNSET:
+ field_dict["enable_email_password"] = enable_email_password
+ if rate_limit_signup is not UNSET:
+ field_dict["rate_limit_signup"] = rate_limit_signup
+ if rate_limit_signin is not UNSET:
+ field_dict["rate_limit_signin"] = rate_limit_signin
+ if rate_limit_token_refresh is not UNSET:
+ field_dict["rate_limit_token_refresh"] = rate_limit_token_refresh
+ if cors_enabled is not UNSET:
+ field_dict["cors_enabled"] = cors_enabled
+ if cors_allowed_origins is not UNSET:
+ field_dict["cors_allowed_origins"] = cors_allowed_origins
+ if enable_anonymous_signins is not UNSET:
+ field_dict["enable_anonymous_signins"] = enable_anonymous_signins
+ if allowed_email_domains is not UNSET:
+ field_dict["allowed_email_domains"] = allowed_email_domains
+ if allowed_email_domains_mode is not UNSET:
+ field_dict["allowed_email_domains_mode"] = allowed_email_domains_mode
+ if platform_token_ttl is not UNSET:
+ field_dict["platform_token_ttl"] = platform_token_ttl
+ if allow_password_reset is not UNSET:
+ field_dict["allow_password_reset"] = allow_password_reset
+ if password_reset_timeout is not UNSET:
+ field_dict["password_reset_timeout"] = password_reset_timeout
+ if max_password_history is not UNSET:
+ field_dict["max_password_history"] = max_password_history
+ if cors_allow_credentials is not UNSET:
+ field_dict["cors_allow_credentials"] = cors_allow_credentials
+ if cors_max_age is not UNSET:
+ field_dict["cors_max_age"] = cors_max_age
+ if require_email_confirmation is not UNSET:
+ field_dict["require_email_confirmation"] = require_email_confirmation
+ if email_confirmation_timeout is not UNSET:
+ field_dict["email_confirmation_timeout"] = email_confirmation_timeout
+ if auto_link_verified_oauth is not UNSET:
+ field_dict["auto_link_verified_oauth"] = auto_link_verified_oauth
+ if email_enabled is not UNSET:
+ field_dict["email_enabled"] = email_enabled
+ if email_from_address is not UNSET:
+ field_dict["email_from_address"] = email_from_address
+ if email_from_name is not UNSET:
+ field_dict["email_from_name"] = email_from_name
+ if smtp_host is not UNSET:
+ field_dict["smtp_host"] = smtp_host
+ if smtp_port is not UNSET:
+ field_dict["smtp_port"] = smtp_port
+ if smtp_username is not UNSET:
+ field_dict["smtp_username"] = smtp_username
+ if smtp_password_configured is not UNSET:
+ field_dict["smtp_password_configured"] = smtp_password_configured
+ if smtp_use_tls is not UNSET:
+ field_dict["smtp_use_tls"] = smtp_use_tls
+ if email_confirmation_subject is not UNSET:
+ field_dict["email_confirmation_subject"] = email_confirmation_subject
+ if email_password_reset_subject is not UNSET:
+ field_dict["email_password_reset_subject"] = email_password_reset_subject
+ if email_password_changed_subject is not UNSET:
+ field_dict["email_password_changed_subject"] = email_password_changed_subject
+ if managed_auth_enabled is not UNSET:
+ field_dict["managed_auth_enabled"] = managed_auth_enabled
+ if post_auth_redirect_url is not UNSET:
+ field_dict["post_auth_redirect_url"] = post_auth_redirect_url
+ if allowed_redirect_urls is not UNSET:
+ field_dict["allowed_redirect_urls"] = allowed_redirect_urls
+ if post_logout_redirect_url is not UNSET:
+ field_dict["post_logout_redirect_url"] = post_logout_redirect_url
+ if device_verification_url is not UNSET:
+ field_dict["device_verification_url"] = device_verification_url
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_password_policy import AuthPasswordPolicy
+ d = dict(src_dict)
+ password_policy = AuthPasswordPolicy.from_dict(d.pop("password_policy"))
+
+
+
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ access_token_lifetime = d.pop("access_token_lifetime", UNSET)
+
+ refresh_token_lifetime = d.pop("refresh_token_lifetime", UNSET)
+
+ inactivity_timeout = d.pop("inactivity_timeout", UNSET)
+
+ max_session_duration = d.pop("max_session_duration", UNSET)
+
+ min_password_length = d.pop("min_password_length", UNSET)
+
+ require_uppercase = d.pop("require_uppercase", UNSET)
+
+ require_lowercase = d.pop("require_lowercase", UNSET)
+
+ require_numbers = d.pop("require_numbers", UNSET)
+
+ require_special_chars = d.pop("require_special_chars", UNSET)
+
+ enable_signup = d.pop("enable_signup", UNSET)
+
+ enable_email_password = d.pop("enable_email_password", UNSET)
+
+ rate_limit_signup = d.pop("rate_limit_signup", UNSET)
+
+ rate_limit_signin = d.pop("rate_limit_signin", UNSET)
+
+ rate_limit_token_refresh = d.pop("rate_limit_token_refresh", UNSET)
+
+ cors_enabled = d.pop("cors_enabled", UNSET)
+
+ cors_allowed_origins = cast(list[str], d.pop("cors_allowed_origins", UNSET))
+
+
+ enable_anonymous_signins = d.pop("enable_anonymous_signins", UNSET)
+
+ allowed_email_domains = cast(list[str], d.pop("allowed_email_domains", UNSET))
+
+
+ _allowed_email_domains_mode = d.pop("allowed_email_domains_mode", UNSET)
+ allowed_email_domains_mode: AuthConfigAllowedEmailDomainsMode | Unset
+ if isinstance(_allowed_email_domains_mode, Unset):
+ allowed_email_domains_mode = UNSET
+ else:
+ allowed_email_domains_mode = check_auth_config_allowed_email_domains_mode(_allowed_email_domains_mode)
+
+
+
+
+ platform_token_ttl = d.pop("platform_token_ttl", UNSET)
+
+ allow_password_reset = d.pop("allow_password_reset", UNSET)
+
+ password_reset_timeout = d.pop("password_reset_timeout", UNSET)
+
+ max_password_history = d.pop("max_password_history", UNSET)
+
+ cors_allow_credentials = d.pop("cors_allow_credentials", UNSET)
+
+ cors_max_age = d.pop("cors_max_age", UNSET)
+
+ require_email_confirmation = d.pop("require_email_confirmation", UNSET)
+
+ email_confirmation_timeout = d.pop("email_confirmation_timeout", UNSET)
+
+ auto_link_verified_oauth = d.pop("auto_link_verified_oauth", UNSET)
+
+ email_enabled = d.pop("email_enabled", UNSET)
+
+ email_from_address = d.pop("email_from_address", UNSET)
+
+ email_from_name = d.pop("email_from_name", UNSET)
+
+ smtp_host = d.pop("smtp_host", UNSET)
+
+ smtp_port = d.pop("smtp_port", UNSET)
+
+ smtp_username = d.pop("smtp_username", UNSET)
+
+ smtp_password_configured = d.pop("smtp_password_configured", UNSET)
+
+ smtp_use_tls = d.pop("smtp_use_tls", UNSET)
+
+ email_confirmation_subject = d.pop("email_confirmation_subject", UNSET)
+
+ email_password_reset_subject = d.pop("email_password_reset_subject", UNSET)
+
+ email_password_changed_subject = d.pop("email_password_changed_subject", UNSET)
+
+ managed_auth_enabled = d.pop("managed_auth_enabled", UNSET)
+
+ post_auth_redirect_url = d.pop("post_auth_redirect_url", UNSET)
+
+ allowed_redirect_urls = cast(list[str], d.pop("allowed_redirect_urls", UNSET))
+
+
+ post_logout_redirect_url = d.pop("post_logout_redirect_url", UNSET)
+
+ device_verification_url = d.pop("device_verification_url", UNSET)
+
+ auth_config = cls(
+ password_policy=password_policy,
+ project_id=project_id,
+ access_token_lifetime=access_token_lifetime,
+ refresh_token_lifetime=refresh_token_lifetime,
+ inactivity_timeout=inactivity_timeout,
+ max_session_duration=max_session_duration,
+ min_password_length=min_password_length,
+ require_uppercase=require_uppercase,
+ require_lowercase=require_lowercase,
+ require_numbers=require_numbers,
+ require_special_chars=require_special_chars,
+ enable_signup=enable_signup,
+ enable_email_password=enable_email_password,
+ rate_limit_signup=rate_limit_signup,
+ rate_limit_signin=rate_limit_signin,
+ rate_limit_token_refresh=rate_limit_token_refresh,
+ cors_enabled=cors_enabled,
+ cors_allowed_origins=cors_allowed_origins,
+ enable_anonymous_signins=enable_anonymous_signins,
+ allowed_email_domains=allowed_email_domains,
+ allowed_email_domains_mode=allowed_email_domains_mode,
+ platform_token_ttl=platform_token_ttl,
+ allow_password_reset=allow_password_reset,
+ password_reset_timeout=password_reset_timeout,
+ max_password_history=max_password_history,
+ cors_allow_credentials=cors_allow_credentials,
+ cors_max_age=cors_max_age,
+ require_email_confirmation=require_email_confirmation,
+ email_confirmation_timeout=email_confirmation_timeout,
+ auto_link_verified_oauth=auto_link_verified_oauth,
+ email_enabled=email_enabled,
+ email_from_address=email_from_address,
+ email_from_name=email_from_name,
+ smtp_host=smtp_host,
+ smtp_port=smtp_port,
+ smtp_username=smtp_username,
+ smtp_password_configured=smtp_password_configured,
+ smtp_use_tls=smtp_use_tls,
+ email_confirmation_subject=email_confirmation_subject,
+ email_password_reset_subject=email_password_reset_subject,
+ email_password_changed_subject=email_password_changed_subject,
+ managed_auth_enabled=managed_auth_enabled,
+ post_auth_redirect_url=post_auth_redirect_url,
+ allowed_redirect_urls=allowed_redirect_urls,
+ post_logout_redirect_url=post_logout_redirect_url,
+ device_verification_url=device_verification_url,
+ )
+
+
+ auth_config.additional_properties = d
+ return auth_config
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_config_allowed_email_domains_mode.py b/src/volcano_sdk/_generated/models/auth_config_allowed_email_domains_mode.py
new file mode 100644
index 00000000..8226a24f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_config_allowed_email_domains_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthConfigAllowedEmailDomainsMode = Literal['disabled', 'signup', 'signup_and_signin']
+
+AUTH_CONFIG_ALLOWED_EMAIL_DOMAINS_MODE_VALUES: set[AuthConfigAllowedEmailDomainsMode] = { 'disabled', 'signup', 'signup_and_signin', }
+
+def check_auth_config_allowed_email_domains_mode(value: str) -> AuthConfigAllowedEmailDomainsMode:
+ if value in AUTH_CONFIG_ALLOWED_EMAIL_DOMAINS_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_CONFIG_ALLOWED_EMAIL_DOMAINS_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_confirm_email_body.py b/src/volcano_sdk/_generated/models/auth_confirm_email_body.py
new file mode 100644
index 00000000..77673ec2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_confirm_email_body.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthConfirmEmailBody")
+
+
+
+@_attrs_define
+class AuthConfirmEmailBody:
+ """
+ Attributes:
+ token (str): Confirmation token from email
+ """
+
+ token: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ token = self.token
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "token": token,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ token = d.pop("token")
+
+ auth_confirm_email_body = cls(
+ token=token,
+ )
+
+
+ auth_confirm_email_body.additional_properties = d
+ return auth_confirm_email_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_confirm_email_change_body.py b/src/volcano_sdk/_generated/models/auth_confirm_email_change_body.py
new file mode 100644
index 00000000..f74f26dd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_confirm_email_change_body.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthConfirmEmailChangeBody")
+
+
+
+@_attrs_define
+class AuthConfirmEmailChangeBody:
+ """
+ Attributes:
+ email_change_token (str):
+ """
+
+ email_change_token: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ email_change_token = self.email_change_token
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "email_change_token": email_change_token,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ email_change_token = d.pop("email_change_token")
+
+ auth_confirm_email_change_body = cls(
+ email_change_token=email_change_token,
+ )
+
+
+ auth_confirm_email_change_body.additional_properties = d
+ return auth_confirm_email_change_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_confirm_email_change_response_200.py b/src/volcano_sdk/_generated/models/auth_confirm_email_change_response_200.py
new file mode 100644
index 00000000..b5b665de
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_confirm_email_change_response_200.py
@@ -0,0 +1,102 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_user import AuthUser
+
+
+
+
+
+T = TypeVar("T", bound="AuthConfirmEmailChangeResponse200")
+
+
+
+@_attrs_define
+class AuthConfirmEmailChangeResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ user (AuthUser | Unset):
+ """
+
+ message: str | Unset = UNSET
+ user: AuthUser | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_user import AuthUser
+ message = self.message
+
+ user: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user, Unset):
+ user = self.user.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+ if user is not UNSET:
+ field_dict["user"] = user
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_user import AuthUser
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ _user = d.pop("user", UNSET)
+ user: AuthUser | Unset
+ if isinstance(_user, Unset):
+ user = UNSET
+ else:
+ user = AuthUser.from_dict(_user)
+
+
+
+
+ auth_confirm_email_change_response_200 = cls(
+ message=message,
+ user=user,
+ )
+
+
+ auth_confirm_email_change_response_200.additional_properties = d
+ return auth_confirm_email_change_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_confirm_email_response_200.py b/src/volcano_sdk/_generated/models/auth_confirm_email_response_200.py
new file mode 100644
index 00000000..8849a92a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_confirm_email_response_200.py
@@ -0,0 +1,92 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_confirm_email_response_200_message import AuthConfirmEmailResponse200Message
+from ..models.auth_confirm_email_response_200_message import check_auth_confirm_email_response_200_message
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthConfirmEmailResponse200")
+
+
+
+@_attrs_define
+class AuthConfirmEmailResponse200:
+ """
+ Attributes:
+ message (AuthConfirmEmailResponse200Message | Unset):
+ """
+
+ message: AuthConfirmEmailResponse200Message | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message: str | Unset = UNSET
+ if not isinstance(self.message, Unset):
+ message = self.message
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ _message = d.pop("message", UNSET)
+ message: AuthConfirmEmailResponse200Message | Unset
+ if isinstance(_message, Unset):
+ message = UNSET
+ else:
+ message = check_auth_confirm_email_response_200_message(_message)
+
+
+
+
+ auth_confirm_email_response_200 = cls(
+ message=message,
+ )
+
+
+ auth_confirm_email_response_200.additional_properties = d
+ return auth_confirm_email_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_confirm_email_response_200_message.py b/src/volcano_sdk/_generated/models/auth_confirm_email_response_200_message.py
new file mode 100644
index 00000000..c29f7996
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_confirm_email_response_200_message.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthConfirmEmailResponse200Message = Literal['Email already confirmed', 'Email confirmed successfully']
+
+AUTH_CONFIRM_EMAIL_RESPONSE_200_MESSAGE_VALUES: set[AuthConfirmEmailResponse200Message] = { 'Email already confirmed', 'Email confirmed successfully', }
+
+def check_auth_confirm_email_response_200_message(value: str) -> AuthConfirmEmailResponse200Message:
+ if value in AUTH_CONFIRM_EMAIL_RESPONSE_200_MESSAGE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_CONFIRM_EMAIL_RESPONSE_200_MESSAGE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_convert_anonymous_body.py b/src/volcano_sdk/_generated/models/auth_convert_anonymous_body.py
new file mode 100644
index 00000000..e26d48e6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_convert_anonymous_body.py
@@ -0,0 +1,110 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_convert_anonymous_body_user_metadata import AuthConvertAnonymousBodyUserMetadata
+
+
+
+
+
+T = TypeVar("T", bound="AuthConvertAnonymousBody")
+
+
+
+@_attrs_define
+class AuthConvertAnonymousBody:
+ """
+ Attributes:
+ email (str):
+ password (str): Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ user_metadata (AuthConvertAnonymousBodyUserMetadata | Unset):
+ """
+
+ email: str
+ password: str
+ user_metadata: AuthConvertAnonymousBodyUserMetadata | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_convert_anonymous_body_user_metadata import AuthConvertAnonymousBodyUserMetadata
+ email = self.email
+
+ password = self.password
+
+ user_metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user_metadata, Unset):
+ user_metadata = self.user_metadata.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "email": email,
+ "password": password,
+ })
+ if user_metadata is not UNSET:
+ field_dict["user_metadata"] = user_metadata
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_convert_anonymous_body_user_metadata import AuthConvertAnonymousBodyUserMetadata
+ d = dict(src_dict)
+ email = d.pop("email")
+
+ password = d.pop("password")
+
+ _user_metadata = d.pop("user_metadata", UNSET)
+ user_metadata: AuthConvertAnonymousBodyUserMetadata | Unset
+ if isinstance(_user_metadata, Unset):
+ user_metadata = UNSET
+ else:
+ user_metadata = AuthConvertAnonymousBodyUserMetadata.from_dict(_user_metadata)
+
+
+
+
+ auth_convert_anonymous_body = cls(
+ email=email,
+ password=password,
+ user_metadata=user_metadata,
+ )
+
+
+ auth_convert_anonymous_body.additional_properties = d
+ return auth_convert_anonymous_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_convert_anonymous_body_user_metadata.py b/src/volcano_sdk/_generated/models/auth_convert_anonymous_body_user_metadata.py
new file mode 100644
index 00000000..0476273e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_convert_anonymous_body_user_metadata.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthConvertAnonymousBodyUserMetadata")
+
+
+
+@_attrs_define
+class AuthConvertAnonymousBodyUserMetadata:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auth_convert_anonymous_body_user_metadata = cls(
+ )
+
+
+ auth_convert_anonymous_body_user_metadata.additional_properties = d
+ return auth_convert_anonymous_body_user_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_convert_anonymous_response_200.py b/src/volcano_sdk/_generated/models/auth_convert_anonymous_response_200.py
new file mode 100644
index 00000000..a4c69419
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_convert_anonymous_response_200.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_user import AuthUser
+
+
+
+
+
+T = TypeVar("T", bound="AuthConvertAnonymousResponse200")
+
+
+
+@_attrs_define
+class AuthConvertAnonymousResponse200:
+ """
+ Attributes:
+ user (AuthUser | Unset):
+ """
+
+ user: AuthUser | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_user import AuthUser
+ user: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user, Unset):
+ user = self.user.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if user is not UNSET:
+ field_dict["user"] = user
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_user import AuthUser
+ d = dict(src_dict)
+ _user = d.pop("user", UNSET)
+ user: AuthUser | Unset
+ if isinstance(_user, Unset):
+ user = UNSET
+ else:
+ user = AuthUser.from_dict(_user)
+
+
+
+
+ auth_convert_anonymous_response_200 = cls(
+ user=user,
+ )
+
+
+ auth_convert_anonymous_response_200.additional_properties = d
+ return auth_convert_anonymous_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_device_authorize_body.py b/src/volcano_sdk/_generated/models/auth_device_authorize_body.py
new file mode 100644
index 00000000..e9e38333
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_device_authorize_body.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthDeviceAuthorizeBody")
+
+
+
+@_attrs_define
+class AuthDeviceAuthorizeBody:
+ """
+ Attributes:
+ client_id (str): Enabled `device` OAuth client ID for the target project
+ """
+
+ client_id: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ client_id = self.client_id
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "client_id": client_id,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ client_id = d.pop("client_id")
+
+ auth_device_authorize_body = cls(
+ client_id=client_id,
+ )
+
+
+ auth_device_authorize_body.additional_properties = d
+ return auth_device_authorize_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_device_token_body.py b/src/volcano_sdk/_generated/models/auth_device_token_body.py
new file mode 100644
index 00000000..803bc48d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_device_token_body.py
@@ -0,0 +1,98 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_device_token_body_grant_type import AuthDeviceTokenBodyGrantType
+from ..models.auth_device_token_body_grant_type import check_auth_device_token_body_grant_type
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthDeviceTokenBody")
+
+
+
+@_attrs_define
+class AuthDeviceTokenBody:
+ """
+ Attributes:
+ grant_type (AuthDeviceTokenBodyGrantType):
+ device_code (str):
+ client_id (str):
+ """
+
+ grant_type: AuthDeviceTokenBodyGrantType
+ device_code: str
+ client_id: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ grant_type: str = self.grant_type
+
+ device_code = self.device_code
+
+ client_id = self.client_id
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "grant_type": grant_type,
+ "device_code": device_code,
+ "client_id": client_id,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ grant_type = check_auth_device_token_body_grant_type(d.pop("grant_type"))
+
+
+
+
+ device_code = d.pop("device_code")
+
+ client_id = d.pop("client_id")
+
+ auth_device_token_body = cls(
+ grant_type=grant_type,
+ device_code=device_code,
+ client_id=client_id,
+ )
+
+
+ auth_device_token_body.additional_properties = d
+ return auth_device_token_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_device_token_body_grant_type.py b/src/volcano_sdk/_generated/models/auth_device_token_body_grant_type.py
new file mode 100644
index 00000000..2b057033
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_device_token_body_grant_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthDeviceTokenBodyGrantType = Literal['urn:ietf:params:oauth:grant-type:device_code']
+
+AUTH_DEVICE_TOKEN_BODY_GRANT_TYPE_VALUES: set[AuthDeviceTokenBodyGrantType] = { 'urn:ietf:params:oauth:grant-type:device_code', }
+
+def check_auth_device_token_body_grant_type(value: str) -> AuthDeviceTokenBodyGrantType:
+ if value in AUTH_DEVICE_TOKEN_BODY_GRANT_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_DEVICE_TOKEN_BODY_GRANT_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_device_verify_body.py b/src/volcano_sdk/_generated/models/auth_device_verify_body.py
new file mode 100644
index 00000000..c71650fa
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_device_verify_body.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_device_verify_body_action import AuthDeviceVerifyBodyAction
+from ..models.auth_device_verify_body_action import check_auth_device_verify_body_action
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthDeviceVerifyBody")
+
+
+
+@_attrs_define
+class AuthDeviceVerifyBody:
+ """
+ Attributes:
+ user_code (str):
+ action (AuthDeviceVerifyBodyAction | Unset): Default: 'approve'.
+ """
+
+ user_code: str
+ action: AuthDeviceVerifyBodyAction | Unset = 'approve'
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ user_code = self.user_code
+
+ action: str | Unset = UNSET
+ if not isinstance(self.action, Unset):
+ action = self.action
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "user_code": user_code,
+ })
+ if action is not UNSET:
+ field_dict["action"] = action
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ user_code = d.pop("user_code")
+
+ _action = d.pop("action", UNSET)
+ action: AuthDeviceVerifyBodyAction | Unset
+ if isinstance(_action, Unset):
+ action = UNSET
+ else:
+ action = check_auth_device_verify_body_action(_action)
+
+
+
+
+ auth_device_verify_body = cls(
+ user_code=user_code,
+ action=action,
+ )
+
+
+ auth_device_verify_body.additional_properties = d
+ return auth_device_verify_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_device_verify_body_action.py b/src/volcano_sdk/_generated/models/auth_device_verify_body_action.py
new file mode 100644
index 00000000..7ad1dd7a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_device_verify_body_action.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthDeviceVerifyBodyAction = Literal['approve', 'deny']
+
+AUTH_DEVICE_VERIFY_BODY_ACTION_VALUES: set[AuthDeviceVerifyBodyAction] = { 'approve', 'deny', }
+
+def check_auth_device_verify_body_action(value: str) -> AuthDeviceVerifyBodyAction:
+ if value in AUTH_DEVICE_VERIFY_BODY_ACTION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_DEVICE_VERIFY_BODY_ACTION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_device_verify_response_200.py b/src/volcano_sdk/_generated/models/auth_device_verify_response_200.py
new file mode 100644
index 00000000..b841279b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_device_verify_response_200.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthDeviceVerifyResponse200")
+
+
+
+@_attrs_define
+class AuthDeviceVerifyResponse200:
+ """
+ Attributes:
+ success (bool | Unset):
+ status (str | Unset):
+ """
+
+ success: bool | Unset = UNSET
+ status: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ success = self.success
+
+ status = self.status
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if success is not UNSET:
+ field_dict["success"] = success
+ if status is not UNSET:
+ field_dict["status"] = status
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ success = d.pop("success", UNSET)
+
+ status = d.pop("status", UNSET)
+
+ auth_device_verify_response_200 = cls(
+ success=success,
+ status=status,
+ )
+
+
+ auth_device_verify_response_200.additional_properties = d
+ return auth_device_verify_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_forgot_password_body.py b/src/volcano_sdk/_generated/models/auth_forgot_password_body.py
new file mode 100644
index 00000000..1d51cafb
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_forgot_password_body.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthForgotPasswordBody")
+
+
+
+@_attrs_define
+class AuthForgotPasswordBody:
+ """
+ Attributes:
+ email (str):
+ """
+
+ email: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ email = self.email
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "email": email,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ email = d.pop("email")
+
+ auth_forgot_password_body = cls(
+ email=email,
+ )
+
+
+ auth_forgot_password_body.additional_properties = d
+ return auth_forgot_password_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_forgot_password_response_200.py b/src/volcano_sdk/_generated/models/auth_forgot_password_response_200.py
new file mode 100644
index 00000000..63625e51
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_forgot_password_response_200.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthForgotPasswordResponse200")
+
+
+
+@_attrs_define
+class AuthForgotPasswordResponse200:
+ """
+ Attributes:
+ message (str | Unset): Example: If the email exists, a password reset link has been sent.
+ """
+
+ message: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ auth_forgot_password_response_200 = cls(
+ message=message,
+ )
+
+
+ auth_forgot_password_response_200.additional_properties = d
+ return auth_forgot_password_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_get_my_sessions_response_200.py b/src/volcano_sdk/_generated/models/auth_get_my_sessions_response_200.py
new file mode 100644
index 00000000..082a4539
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_get_my_sessions_response_200.py
@@ -0,0 +1,190 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_session import AuthSession
+
+
+
+
+
+T = TypeVar("T", bound="AuthGetMySessionsResponse200")
+
+
+
+@_attrs_define
+class AuthGetMySessionsResponse200:
+ """
+ Attributes:
+ sessions (list[AuthSession] | Unset):
+ total (int | Unset): Total number of sessions
+ page (int | Unset): Current page number
+ limit (int | Unset): Number of sessions per page
+ total_pages (int | Unset): Total number of pages
+ data (list[AuthSession] | Unset): Sessions for this page (cursor pagination only)
+ has_more (bool | Unset): Whether a further page exists (cursor pagination only)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only). Send as
+ `ending_before`.
+ """
+
+ sessions: list[AuthSession] | Unset = UNSET
+ total: int | Unset = UNSET
+ page: int | Unset = UNSET
+ limit: int | Unset = UNSET
+ total_pages: int | Unset = UNSET
+ data: list[AuthSession] | Unset = UNSET
+ has_more: bool | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_session import AuthSession
+ sessions: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.sessions, Unset):
+ sessions = []
+ for sessions_item_data in self.sessions:
+ sessions_item = sessions_item_data.to_dict()
+ sessions.append(sessions_item)
+
+
+
+ total = self.total
+
+ page = self.page
+
+ limit = self.limit
+
+ total_pages = self.total_pages
+
+ data: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.data, Unset):
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ has_more = self.has_more
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if sessions is not UNSET:
+ field_dict["sessions"] = sessions
+ if total is not UNSET:
+ field_dict["total"] = total
+ if page is not UNSET:
+ field_dict["page"] = page
+ if limit is not UNSET:
+ field_dict["limit"] = limit
+ if total_pages is not UNSET:
+ field_dict["total_pages"] = total_pages
+ if data is not UNSET:
+ field_dict["data"] = data
+ if has_more is not UNSET:
+ field_dict["has_more"] = has_more
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_session import AuthSession
+ d = dict(src_dict)
+ _sessions = d.pop("sessions", UNSET)
+ sessions: list[AuthSession] | Unset = UNSET
+ if _sessions is not UNSET:
+ sessions = []
+ for sessions_item_data in _sessions:
+ sessions_item = AuthSession.from_dict(sessions_item_data)
+
+
+
+ sessions.append(sessions_item)
+
+
+ total = d.pop("total", UNSET)
+
+ page = d.pop("page", UNSET)
+
+ limit = d.pop("limit", UNSET)
+
+ total_pages = d.pop("total_pages", UNSET)
+
+ _data = d.pop("data", UNSET)
+ data: list[AuthSession] | Unset = UNSET
+ if _data is not UNSET:
+ data = []
+ for data_item_data in _data:
+ data_item = AuthSession.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ has_more = d.pop("has_more", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ auth_get_my_sessions_response_200 = cls(
+ sessions=sessions,
+ total=total,
+ page=page,
+ limit=limit,
+ total_pages=total_pages,
+ data=data,
+ has_more=has_more,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ auth_get_my_sessions_response_200.additional_properties = d
+ return auth_get_my_sessions_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_get_my_sessions_sort.py b/src/volcano_sdk/_generated/models/auth_get_my_sessions_sort.py
new file mode 100644
index 00000000..36282dc6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_get_my_sessions_sort.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthGetMySessionsSort = Literal['created_at', 'last_activity']
+
+AUTH_GET_MY_SESSIONS_SORT_VALUES: set[AuthGetMySessionsSort] = { 'created_at', 'last_activity', }
+
+def check_auth_get_my_sessions_sort(value: str) -> AuthGetMySessionsSort:
+ if value in AUTH_GET_MY_SESSIONS_SORT_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_GET_MY_SESSIONS_SORT_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_get_my_sessions_status.py b/src/volcano_sdk/_generated/models/auth_get_my_sessions_status.py
new file mode 100644
index 00000000..411af729
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_get_my_sessions_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthGetMySessionsStatus = Literal['active', 'expired']
+
+AUTH_GET_MY_SESSIONS_STATUS_VALUES: set[AuthGetMySessionsStatus] = { 'active', 'expired', }
+
+def check_auth_get_my_sessions_status(value: str) -> AuthGetMySessionsStatus:
+ if value in AUTH_GET_MY_SESSIONS_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_GET_MY_SESSIONS_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_get_user_response_200.py b/src/volcano_sdk/_generated/models/auth_get_user_response_200.py
new file mode 100644
index 00000000..1f486c8b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_get_user_response_200.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_user import AuthUser
+
+
+
+
+
+T = TypeVar("T", bound="AuthGetUserResponse200")
+
+
+
+@_attrs_define
+class AuthGetUserResponse200:
+ """
+ Attributes:
+ user (AuthUser | Unset):
+ """
+
+ user: AuthUser | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_user import AuthUser
+ user: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user, Unset):
+ user = self.user.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if user is not UNSET:
+ field_dict["user"] = user
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_user import AuthUser
+ d = dict(src_dict)
+ _user = d.pop("user", UNSET)
+ user: AuthUser | Unset
+ if isinstance(_user, Unset):
+ user = UNSET
+ else:
+ user = AuthUser.from_dict(_user)
+
+
+
+
+ auth_get_user_response_200 = cls(
+ user=user,
+ )
+
+
+ auth_get_user_response_200.additional_properties = d
+ return auth_get_user_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_hosted_page.py b/src/volcano_sdk/_generated/models/auth_hosted_page.py
new file mode 100644
index 00000000..c3fecb52
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_hosted_page.py
@@ -0,0 +1,188 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.hosted_auth_page_type import check_hosted_auth_page_type
+from ..models.hosted_auth_page_type import HostedAuthPageType
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthHostedPage")
+
+
+
+@_attrs_define
+class AuthHostedPage:
+ """
+ Attributes:
+ id (UUID | Unset):
+ project_id (UUID | Unset):
+ page_type (HostedAuthPageType | Unset):
+ html (str | Unset): HTML content for this page type.
+ css (str | Unset): CSS content for this page type.
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID | Unset = UNSET
+ project_id: UUID | Unset = UNSET
+ page_type: HostedAuthPageType | Unset = UNSET
+ html: str | Unset = UNSET
+ css: str | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id: str | Unset = UNSET
+ if not isinstance(self.id, Unset):
+ id = str(self.id)
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ page_type: str | Unset = UNSET
+ if not isinstance(self.page_type, Unset):
+ page_type = self.page_type
+
+
+ html = self.html
+
+ css = self.css
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if id is not UNSET:
+ field_dict["id"] = id
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if page_type is not UNSET:
+ field_dict["page_type"] = page_type
+ if html is not UNSET:
+ field_dict["html"] = html
+ if css is not UNSET:
+ field_dict["css"] = css
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ _id = d.pop("id", UNSET)
+ id: UUID | Unset
+ if isinstance(_id, Unset):
+ id = UNSET
+ else:
+ id = UUID(_id)
+
+
+
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ _page_type = d.pop("page_type", UNSET)
+ page_type: HostedAuthPageType | Unset
+ if isinstance(_page_type, Unset):
+ page_type = UNSET
+ else:
+ page_type = check_hosted_auth_page_type(_page_type)
+
+
+
+
+ html = d.pop("html", UNSET)
+
+ css = d.pop("css", UNSET)
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ auth_hosted_page = cls(
+ id=id,
+ project_id=project_id,
+ page_type=page_type,
+ html=html,
+ css=css,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ auth_hosted_page.additional_properties = d
+ return auth_hosted_page
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_hosted_page_defaults.py b/src/volcano_sdk/_generated/models/auth_hosted_page_defaults.py
new file mode 100644
index 00000000..cf9984cd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_hosted_page_defaults.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthHostedPageDefaults")
+
+
+
+@_attrs_define
+class AuthHostedPageDefaults:
+ """ The starting point for an unsaved page: the theme shell we render for the
+ built-in page plus its stylesheet. Valid input to the update endpoint —
+ it carries no script, meta, or link tags.
+
+ Attributes:
+ html (str): Body shell markup containing the runtime render root.
+ css (str): The built-in stylesheet, themed by the customer.
+ """
+
+ html: str
+ css: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ html = self.html
+
+ css = self.css
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "html": html,
+ "css": css,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ html = d.pop("html")
+
+ css = d.pop("css")
+
+ auth_hosted_page_defaults = cls(
+ html=html,
+ css=css,
+ )
+
+
+ auth_hosted_page_defaults.additional_properties = d
+ return auth_hosted_page_defaults
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_hosted_page_response.py b/src/volcano_sdk/_generated/models/auth_hosted_page_response.py
new file mode 100644
index 00000000..a9b810ad
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_hosted_page_response.py
@@ -0,0 +1,133 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_hosted_page import AuthHostedPage
+ from ..models.auth_hosted_page_defaults import AuthHostedPageDefaults
+ from ..models.auth_hosted_page_runtime import AuthHostedPageRuntime
+
+
+
+
+
+T = TypeVar("T", bound="AuthHostedPageResponse")
+
+
+
+@_attrs_define
+class AuthHostedPageResponse:
+ """
+ Attributes:
+ page (AuthHostedPage | None): The saved page, or null when the project has not customized this page type yet.
+ defaults (AuthHostedPageDefaults): The starting point for an unsaved page: the theme shell we render for the
+ built-in page plus its stylesheet. Valid input to the update endpoint —
+ it carries no script, meta, or link tags.
+ runtime (AuthHostedPageRuntime): The server-owned behavior of a hosted page. Clients compose previews from
+ this instead of reimplementing the page, so a preview cannot drift from
+ what is actually served.
+ """
+
+ page: AuthHostedPage | None
+ defaults: AuthHostedPageDefaults
+ runtime: AuthHostedPageRuntime
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_hosted_page import AuthHostedPage
+ from ..models.auth_hosted_page_defaults import AuthHostedPageDefaults
+ from ..models.auth_hosted_page_runtime import AuthHostedPageRuntime
+ page: dict[str, Any] | None
+ if isinstance(self.page, AuthHostedPage):
+ page = self.page.to_dict()
+ else:
+ page = self.page
+
+ defaults = self.defaults.to_dict()
+
+ runtime = self.runtime.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "page": page,
+ "defaults": defaults,
+ "runtime": runtime,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_hosted_page import AuthHostedPage
+ from ..models.auth_hosted_page_defaults import AuthHostedPageDefaults
+ from ..models.auth_hosted_page_runtime import AuthHostedPageRuntime
+ d = dict(src_dict)
+ def _parse_page(data: object) -> AuthHostedPage | None:
+ if data is None:
+ return data
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ page_type_1 = AuthHostedPage.from_dict(data)
+
+
+
+ return page_type_1
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(AuthHostedPage | None, data)
+
+ page = _parse_page(d.pop("page"))
+
+
+ defaults = AuthHostedPageDefaults.from_dict(d.pop("defaults"))
+
+
+
+
+ runtime = AuthHostedPageRuntime.from_dict(d.pop("runtime"))
+
+
+
+
+ auth_hosted_page_response = cls(
+ page=page,
+ defaults=defaults,
+ runtime=runtime,
+ )
+
+
+ auth_hosted_page_response.additional_properties = d
+ return auth_hosted_page_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_hosted_page_runtime.py b/src/volcano_sdk/_generated/models/auth_hosted_page_runtime.py
new file mode 100644
index 00000000..658db63d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_hosted_page_runtime.py
@@ -0,0 +1,97 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthHostedPageRuntime")
+
+
+
+@_attrs_define
+class AuthHostedPageRuntime:
+ """ The server-owned behavior of a hosted page. Clients compose previews from
+ this instead of reimplementing the page, so a preview cannot drift from
+ what is actually served.
+
+ Attributes:
+ root_id (str): Element id the runtime script renders into. Markup carrying it opts into the theme-shell
+ contract.
+ script (str): The runtime script injected into the rendered page.
+ mock_prelude (str): Preview harness that supplies request params and stubs the hosted-auth API. Never served on
+ a real page.
+ """
+
+ root_id: str
+ script: str
+ mock_prelude: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ root_id = self.root_id
+
+ script = self.script
+
+ mock_prelude = self.mock_prelude
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "root_id": root_id,
+ "script": script,
+ "mock_prelude": mock_prelude,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ root_id = d.pop("root_id")
+
+ script = d.pop("script")
+
+ mock_prelude = d.pop("mock_prelude")
+
+ auth_hosted_page_runtime = cls(
+ root_id=root_id,
+ script=script,
+ mock_prelude=mock_prelude,
+ )
+
+
+ auth_hosted_page_runtime.additional_properties = d
+ return auth_hosted_page_runtime
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_identities_response.py b/src/volcano_sdk/_generated/models/auth_identities_response.py
new file mode 100644
index 00000000..a72aec40
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_identities_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_identity import AuthIdentity
+
+
+
+
+
+T = TypeVar("T", bound="AuthIdentitiesResponse")
+
+
+
+@_attrs_define
+class AuthIdentitiesResponse:
+ """
+ Attributes:
+ identities (list[AuthIdentity]):
+ """
+
+ identities: list[AuthIdentity]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_identity import AuthIdentity
+ identities = []
+ for identities_item_data in self.identities:
+ identities_item = identities_item_data.to_dict()
+ identities.append(identities_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "identities": identities,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_identity import AuthIdentity
+ d = dict(src_dict)
+ identities = []
+ _identities = d.pop("identities")
+ for identities_item_data in (_identities):
+ identities_item = AuthIdentity.from_dict(identities_item_data)
+
+
+
+ identities.append(identities_item)
+
+
+ auth_identities_response = cls(
+ identities=identities,
+ )
+
+
+ auth_identities_response.additional_properties = d
+ return auth_identities_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_identity.py b/src/volcano_sdk/_generated/models/auth_identity.py
new file mode 100644
index 00000000..2ed7fe04
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_identity.py
@@ -0,0 +1,119 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthIdentity")
+
+
+
+@_attrs_define
+class AuthIdentity:
+ """ A real email identity owned by the account. One account can own multiple
+ identities (for example a work email plus a personal email linked via OAuth).
+
+ Attributes:
+ id (UUID): Unique identity identifier
+ email (str): The email address this identity represents
+ email_verified (bool): Whether ownership of this email has been verified
+ is_primary (bool): Whether the account's primary sign-in method resolves to this identity
+ created_at (datetime.datetime):
+ """
+
+ id: UUID
+ email: str
+ email_verified: bool
+ is_primary: bool
+ created_at: datetime.datetime
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ email = self.email
+
+ email_verified = self.email_verified
+
+ is_primary = self.is_primary
+
+ created_at = self.created_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "email": email,
+ "email_verified": email_verified,
+ "is_primary": is_primary,
+ "created_at": created_at,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ email = d.pop("email")
+
+ email_verified = d.pop("email_verified")
+
+ is_primary = d.pop("is_primary")
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ auth_identity = cls(
+ id=id,
+ email=email,
+ email_verified=email_verified,
+ is_primary=is_primary,
+ created_at=created_at,
+ )
+
+
+ auth_identity.additional_properties = d
+ return auth_identity
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_insights_interval.py b/src/volcano_sdk/_generated/models/auth_insights_interval.py
new file mode 100644
index 00000000..4b9d18a6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_insights_interval.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthInsightsInterval = Literal['day', 'month', 'week']
+
+AUTH_INSIGHTS_INTERVAL_VALUES: set[AuthInsightsInterval] = { 'day', 'month', 'week', }
+
+def check_auth_insights_interval(value: str) -> AuthInsightsInterval:
+ if value in AUTH_INSIGHTS_INTERVAL_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_INSIGHTS_INTERVAL_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_insights_response.py b/src/volcano_sdk/_generated/models/auth_insights_response.py
new file mode 100644
index 00000000..6e732a47
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_insights_response.py
@@ -0,0 +1,128 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.auth_insights_series_point import AuthInsightsSeriesPoint
+ from ..models.auth_insights_summary import AuthInsightsSummary
+ from ..models.auth_insights_window import AuthInsightsWindow
+
+
+
+
+
+T = TypeVar("T", bound="AuthInsightsResponse")
+
+
+
+@_attrs_define
+class AuthInsightsResponse:
+ """
+ Attributes:
+ project_id (UUID):
+ observed_at (datetime.datetime):
+ window (AuthInsightsWindow):
+ summary (AuthInsightsSummary):
+ series (list[AuthInsightsSeriesPoint]):
+ """
+
+ project_id: UUID
+ observed_at: datetime.datetime
+ window: AuthInsightsWindow
+ summary: AuthInsightsSummary
+ series: list[AuthInsightsSeriesPoint]
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_insights_series_point import AuthInsightsSeriesPoint
+ from ..models.auth_insights_summary import AuthInsightsSummary
+ from ..models.auth_insights_window import AuthInsightsWindow
+ project_id = str(self.project_id)
+
+ observed_at = self.observed_at.isoformat()
+
+ window = self.window.to_dict()
+
+ summary = self.summary.to_dict()
+
+ series = []
+ for series_item_data in self.series:
+ series_item = series_item_data.to_dict()
+ series.append(series_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "project_id": project_id,
+ "observed_at": observed_at,
+ "window": window,
+ "summary": summary,
+ "series": series,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_insights_series_point import AuthInsightsSeriesPoint
+ from ..models.auth_insights_summary import AuthInsightsSummary
+ from ..models.auth_insights_window import AuthInsightsWindow
+ d = dict(src_dict)
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ observed_at = datetime.datetime.fromisoformat(d.pop("observed_at"))
+
+
+
+
+ window = AuthInsightsWindow.from_dict(d.pop("window"))
+
+
+
+
+ summary = AuthInsightsSummary.from_dict(d.pop("summary"))
+
+
+
+
+ series = []
+ _series = d.pop("series")
+ for series_item_data in (_series):
+ series_item = AuthInsightsSeriesPoint.from_dict(series_item_data)
+
+
+
+ series.append(series_item)
+
+
+ auth_insights_response = cls(
+ project_id=project_id,
+ observed_at=observed_at,
+ window=window,
+ summary=summary,
+ series=series,
+ )
+
+ return auth_insights_response
+
diff --git a/src/volcano_sdk/_generated/models/auth_insights_series_point.py b/src/volcano_sdk/_generated/models/auth_insights_series_point.py
new file mode 100644
index 00000000..ceb58f35
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_insights_series_point.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthInsightsSeriesPoint")
+
+
+
+@_attrs_define
+class AuthInsightsSeriesPoint:
+ """
+ Attributes:
+ bucket_start (datetime.date):
+ signups (int): Accounts created during the bucket.
+ signins (int): Successful session creations during the bucket.
+ is_partial (bool): Whether the requested window or observation time clips this bucket.
+ """
+
+ bucket_start: datetime.date
+ signups: int
+ signins: int
+ is_partial: bool
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ bucket_start = self.bucket_start.isoformat()
+
+ signups = self.signups
+
+ signins = self.signins
+
+ is_partial = self.is_partial
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "bucket_start": bucket_start,
+ "signups": signups,
+ "signins": signins,
+ "is_partial": is_partial,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ bucket_start = datetime.date.fromisoformat(d.pop("bucket_start"))
+
+
+
+
+ signups = d.pop("signups")
+
+ signins = d.pop("signins")
+
+ is_partial = d.pop("is_partial")
+
+ auth_insights_series_point = cls(
+ bucket_start=bucket_start,
+ signups=signups,
+ signins=signins,
+ is_partial=is_partial,
+ )
+
+ return auth_insights_series_point
+
diff --git a/src/volcano_sdk/_generated/models/auth_insights_summary.py b/src/volcano_sdk/_generated/models/auth_insights_summary.py
new file mode 100644
index 00000000..37e1380d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_insights_summary.py
@@ -0,0 +1,67 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthInsightsSummary")
+
+
+
+@_attrs_define
+class AuthInsightsSummary:
+ """
+ Attributes:
+ total_users (int): Current auth-user count, matching the auth-user list total.
+ active_users_30d (int): Users with a successful session creation or refresh in the trailing 30 days since
+ activity collection was deployed.
+ """
+
+ total_users: int
+ active_users_30d: int
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ total_users = self.total_users
+
+ active_users_30d = self.active_users_30d
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "total_users": total_users,
+ "active_users_30d": active_users_30d,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ total_users = d.pop("total_users")
+
+ active_users_30d = d.pop("active_users_30d")
+
+ auth_insights_summary = cls(
+ total_users=total_users,
+ active_users_30d=active_users_30d,
+ )
+
+ return auth_insights_summary
+
diff --git a/src/volcano_sdk/_generated/models/auth_insights_window.py b/src/volcano_sdk/_generated/models/auth_insights_window.py
new file mode 100644
index 00000000..7de5f7a4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_insights_window.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_insights_interval import AuthInsightsInterval
+from ..models.auth_insights_interval import check_auth_insights_interval
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthInsightsWindow")
+
+
+
+@_attrs_define
+class AuthInsightsWindow:
+ """
+ Attributes:
+ from_ (datetime.date):
+ to (datetime.date):
+ interval (AuthInsightsInterval):
+ """
+
+ from_: datetime.date
+ to: datetime.date
+ interval: AuthInsightsInterval
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from_ = self.from_.isoformat()
+
+ to = self.to.isoformat()
+
+ interval: str = self.interval
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "from": from_,
+ "to": to,
+ "interval": interval,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ from_ = datetime.date.fromisoformat(d.pop("from"))
+
+
+
+
+ to = datetime.date.fromisoformat(d.pop("to"))
+
+
+
+
+ interval = check_auth_insights_interval(d.pop("interval"))
+
+
+
+
+ auth_insights_window = cls(
+ from_=from_,
+ to=to,
+ interval=interval,
+ )
+
+ return auth_insights_window
+
diff --git a/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_provider.py b/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_provider.py
new file mode 100644
index 00000000..896afa10
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthLinkOAuthProviderProvider = Literal['apple', 'github', 'google', 'microsoft']
+
+AUTH_LINK_O_AUTH_PROVIDER_PROVIDER_VALUES: set[AuthLinkOAuthProviderProvider] = { 'apple', 'github', 'google', 'microsoft', }
+
+def check_auth_link_o_auth_provider_provider(value: str) -> AuthLinkOAuthProviderProvider:
+ if value in AUTH_LINK_O_AUTH_PROVIDER_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_LINK_O_AUTH_PROVIDER_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_200.py b/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_200.py
new file mode 100644
index 00000000..3a6f53a6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_200.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthLinkOAuthProviderResponse200")
+
+
+
+@_attrs_define
+class AuthLinkOAuthProviderResponse200:
+ """
+ Attributes:
+ authorization_url (str | Unset):
+ """
+
+ authorization_url: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ authorization_url = self.authorization_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if authorization_url is not UNSET:
+ field_dict["authorization_url"] = authorization_url
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ authorization_url = d.pop("authorization_url", UNSET)
+
+ auth_link_o_auth_provider_response_200 = cls(
+ authorization_url=authorization_url,
+ )
+
+
+ auth_link_o_auth_provider_response_200.additional_properties = d
+ return auth_link_o_auth_provider_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_mode.py b/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_mode.py
new file mode 100644
index 00000000..148c5be5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_link_o_auth_provider_response_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthLinkOAuthProviderResponseMode = Literal['code']
+
+AUTH_LINK_O_AUTH_PROVIDER_RESPONSE_MODE_VALUES: set[AuthLinkOAuthProviderResponseMode] = { 'code', }
+
+def check_auth_link_o_auth_provider_response_mode(value: str) -> AuthLinkOAuthProviderResponseMode:
+ if value in AUTH_LINK_O_AUTH_PROVIDER_RESPONSE_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_LINK_O_AUTH_PROVIDER_RESPONSE_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200.py b/src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200.py
new file mode 100644
index 00000000..13b2a351
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_list_o_auth_providers_response_200_providers_item import AuthListOAuthProvidersResponse200ProvidersItem
+
+
+
+
+
+T = TypeVar("T", bound="AuthListOAuthProvidersResponse200")
+
+
+
+@_attrs_define
+class AuthListOAuthProvidersResponse200:
+ """
+ Attributes:
+ providers (list[AuthListOAuthProvidersResponse200ProvidersItem] | Unset):
+ """
+
+ providers: list[AuthListOAuthProvidersResponse200ProvidersItem] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_list_o_auth_providers_response_200_providers_item import AuthListOAuthProvidersResponse200ProvidersItem
+ providers: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.providers, Unset):
+ providers = []
+ for providers_item_data in self.providers:
+ providers_item = providers_item_data.to_dict()
+ providers.append(providers_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if providers is not UNSET:
+ field_dict["providers"] = providers
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_list_o_auth_providers_response_200_providers_item import AuthListOAuthProvidersResponse200ProvidersItem
+ d = dict(src_dict)
+ _providers = d.pop("providers", UNSET)
+ providers: list[AuthListOAuthProvidersResponse200ProvidersItem] | Unset = UNSET
+ if _providers is not UNSET:
+ providers = []
+ for providers_item_data in _providers:
+ providers_item = AuthListOAuthProvidersResponse200ProvidersItem.from_dict(providers_item_data)
+
+
+
+ providers.append(providers_item)
+
+
+ auth_list_o_auth_providers_response_200 = cls(
+ providers=providers,
+ )
+
+
+ auth_list_o_auth_providers_response_200.additional_properties = d
+ return auth_list_o_auth_providers_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200_providers_item.py b/src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200_providers_item.py
new file mode 100644
index 00000000..4765141f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_list_o_auth_providers_response_200_providers_item.py
@@ -0,0 +1,118 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthListOAuthProvidersResponse200ProvidersItem")
+
+
+
+@_attrs_define
+class AuthListOAuthProvidersResponse200ProvidersItem:
+ """
+ Attributes:
+ provider (str | Unset):
+ linked_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ provider: str | Unset = UNSET
+ linked_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ provider = self.provider
+
+ linked_at: str | Unset = UNSET
+ if not isinstance(self.linked_at, Unset):
+ linked_at = self.linked_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if provider is not UNSET:
+ field_dict["provider"] = provider
+ if linked_at is not UNSET:
+ field_dict["linked_at"] = linked_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ provider = d.pop("provider", UNSET)
+
+ _linked_at = d.pop("linked_at", UNSET)
+ linked_at: datetime.datetime | Unset
+ if isinstance(_linked_at, Unset):
+ linked_at = UNSET
+ else:
+ linked_at = datetime.datetime.fromisoformat(_linked_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ auth_list_o_auth_providers_response_200_providers_item = cls(
+ provider=provider,
+ linked_at=linked_at,
+ updated_at=updated_at,
+ )
+
+
+ auth_list_o_auth_providers_response_200_providers_item.additional_properties = d
+ return auth_list_o_auth_providers_response_200_providers_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_logout_body.py b/src/volcano_sdk/_generated/models/auth_logout_body.py
new file mode 100644
index 00000000..9188bab7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_logout_body.py
@@ -0,0 +1,101 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_logout_body_session_mode import AuthLogoutBodySessionMode
+from ..models.auth_logout_body_session_mode import check_auth_logout_body_session_mode
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthLogoutBody")
+
+
+
+@_attrs_define
+class AuthLogoutBody:
+ """
+ Attributes:
+ refresh_token (str | Unset):
+ session_mode (AuthLogoutBodySessionMode | Unset):
+ """
+
+ refresh_token: str | Unset = UNSET
+ session_mode: AuthLogoutBodySessionMode | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ refresh_token = self.refresh_token
+
+ session_mode: str | Unset = UNSET
+ if not isinstance(self.session_mode, Unset):
+ session_mode = self.session_mode
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if refresh_token is not UNSET:
+ field_dict["refresh_token"] = refresh_token
+ if session_mode is not UNSET:
+ field_dict["session_mode"] = session_mode
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ refresh_token = d.pop("refresh_token", UNSET)
+
+ _session_mode = d.pop("session_mode", UNSET)
+ session_mode: AuthLogoutBodySessionMode | Unset
+ if isinstance(_session_mode, Unset):
+ session_mode = UNSET
+ else:
+ session_mode = check_auth_logout_body_session_mode(_session_mode)
+
+
+
+
+ auth_logout_body = cls(
+ refresh_token=refresh_token,
+ session_mode=session_mode,
+ )
+
+
+ auth_logout_body.additional_properties = d
+ return auth_logout_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_logout_body_session_mode.py b/src/volcano_sdk/_generated/models/auth_logout_body_session_mode.py
new file mode 100644
index 00000000..92bd23b7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_logout_body_session_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthLogoutBodySessionMode = Literal['cookie']
+
+AUTH_LOGOUT_BODY_SESSION_MODE_VALUES: set[AuthLogoutBodySessionMode] = { 'cookie', }
+
+def check_auth_logout_body_session_mode(value: str) -> AuthLogoutBodySessionMode:
+ if value in AUTH_LOGOUT_BODY_SESSION_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_LOGOUT_BODY_SESSION_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_method_summary.py b/src/volcano_sdk/_generated/models/auth_method_summary.py
new file mode 100644
index 00000000..12bb10ae
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_method_summary.py
@@ -0,0 +1,173 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_method_summary_type import AuthMethodSummaryType
+from ..models.auth_method_summary_type import check_auth_method_summary_type
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthMethodSummary")
+
+
+
+@_attrs_define
+class AuthMethodSummary:
+ """ A single sign-in method the account owns (password, an OAuth provider, or an
+ active anonymous method). `is_primary` reflects the account's primary_method_id.
+
+ Attributes:
+ id (UUID): Unique method identifier
+ type_ (AuthMethodSummaryType): The kind of sign-in method
+ identity_id (str): The identity this method signs in to — a UUID for password/oauth methods,
+ empty for anonymous methods.
+ email (str): The email of the method's identity (empty for anonymous)
+ is_primary (bool): Whether this is the account's primary sign-in method
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ provider (str | Unset): OAuth provider name; present only when type is oauth Example: google.
+ last_used_at (datetime.datetime | Unset): When this method was last used to sign in, if ever
+ """
+
+ id: UUID
+ type_: AuthMethodSummaryType
+ identity_id: str
+ email: str
+ is_primary: bool
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ provider: str | Unset = UNSET
+ last_used_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ type_: str = self.type_
+
+ identity_id = self.identity_id
+
+ email = self.email
+
+ is_primary = self.is_primary
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ provider = self.provider
+
+ last_used_at: str | Unset = UNSET
+ if not isinstance(self.last_used_at, Unset):
+ last_used_at = self.last_used_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "type": type_,
+ "identity_id": identity_id,
+ "email": email,
+ "is_primary": is_primary,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if provider is not UNSET:
+ field_dict["provider"] = provider
+ if last_used_at is not UNSET:
+ field_dict["last_used_at"] = last_used_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ type_ = check_auth_method_summary_type(d.pop("type"))
+
+
+
+
+ identity_id = d.pop("identity_id")
+
+ email = d.pop("email")
+
+ is_primary = d.pop("is_primary")
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ provider = d.pop("provider", UNSET)
+
+ _last_used_at = d.pop("last_used_at", UNSET)
+ last_used_at: datetime.datetime | Unset
+ if isinstance(_last_used_at, Unset):
+ last_used_at = UNSET
+ else:
+ last_used_at = datetime.datetime.fromisoformat(_last_used_at)
+
+
+
+
+ auth_method_summary = cls(
+ id=id,
+ type_=type_,
+ identity_id=identity_id,
+ email=email,
+ is_primary=is_primary,
+ created_at=created_at,
+ updated_at=updated_at,
+ provider=provider,
+ last_used_at=last_used_at,
+ )
+
+
+ auth_method_summary.additional_properties = d
+ return auth_method_summary
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_method_summary_type.py b/src/volcano_sdk/_generated/models/auth_method_summary_type.py
new file mode 100644
index 00000000..3570e5fd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_method_summary_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthMethodSummaryType = Literal['anonymous', 'oauth', 'password']
+
+AUTH_METHOD_SUMMARY_TYPE_VALUES: set[AuthMethodSummaryType] = { 'anonymous', 'oauth', 'password', }
+
+def check_auth_method_summary_type(value: str) -> AuthMethodSummaryType:
+ if value in AUTH_METHOD_SUMMARY_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_METHOD_SUMMARY_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_methods_response.py b/src/volcano_sdk/_generated/models/auth_methods_response.py
new file mode 100644
index 00000000..fdcfa9bc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_methods_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_method_summary import AuthMethodSummary
+
+
+
+
+
+T = TypeVar("T", bound="AuthMethodsResponse")
+
+
+
+@_attrs_define
+class AuthMethodsResponse:
+ """
+ Attributes:
+ methods (list[AuthMethodSummary]):
+ """
+
+ methods: list[AuthMethodSummary]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_method_summary import AuthMethodSummary
+ methods = []
+ for methods_item_data in self.methods:
+ methods_item = methods_item_data.to_dict()
+ methods.append(methods_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "methods": methods,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_method_summary import AuthMethodSummary
+ d = dict(src_dict)
+ methods = []
+ _methods = d.pop("methods")
+ for methods_item_data in (_methods):
+ methods_item = AuthMethodSummary.from_dict(methods_item_data)
+
+
+
+ methods.append(methods_item)
+
+
+ auth_methods_response = cls(
+ methods=methods,
+ )
+
+
+ auth_methods_response.additional_properties = d
+ return auth_methods_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_o_auth_authorize_provider.py b/src/volcano_sdk/_generated/models/auth_o_auth_authorize_provider.py
new file mode 100644
index 00000000..59d24064
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_o_auth_authorize_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthOAuthAuthorizeProvider = Literal['apple', 'github', 'google', 'microsoft']
+
+AUTH_O_AUTH_AUTHORIZE_PROVIDER_VALUES: set[AuthOAuthAuthorizeProvider] = { 'apple', 'github', 'google', 'microsoft', }
+
+def check_auth_o_auth_authorize_provider(value: str) -> AuthOAuthAuthorizeProvider:
+ if value in AUTH_O_AUTH_AUTHORIZE_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_O_AUTH_AUTHORIZE_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_o_auth_authorize_response_mode.py b/src/volcano_sdk/_generated/models/auth_o_auth_authorize_response_mode.py
new file mode 100644
index 00000000..e7272e93
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_o_auth_authorize_response_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthOAuthAuthorizeResponseMode = Literal['code']
+
+AUTH_O_AUTH_AUTHORIZE_RESPONSE_MODE_VALUES: set[AuthOAuthAuthorizeResponseMode] = { 'code', }
+
+def check_auth_o_auth_authorize_response_mode(value: str) -> AuthOAuthAuthorizeResponseMode:
+ if value in AUTH_O_AUTH_AUTHORIZE_RESPONSE_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_O_AUTH_AUTHORIZE_RESPONSE_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_o_auth_callback_provider.py b/src/volcano_sdk/_generated/models/auth_o_auth_callback_provider.py
new file mode 100644
index 00000000..4bb582c6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_o_auth_callback_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthOAuthCallbackProvider = Literal['apple', 'github', 'google', 'microsoft']
+
+AUTH_O_AUTH_CALLBACK_PROVIDER_VALUES: set[AuthOAuthCallbackProvider] = { 'apple', 'github', 'google', 'microsoft', }
+
+def check_auth_o_auth_callback_provider(value: str) -> AuthOAuthCallbackProvider:
+ if value in AUTH_O_AUTH_CALLBACK_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_O_AUTH_CALLBACK_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_o_auth_exchange_body.py b/src/volcano_sdk/_generated/models/auth_o_auth_exchange_body.py
new file mode 100644
index 00000000..d2ff9f6a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_o_auth_exchange_body.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthOAuthExchangeBody")
+
+
+
+@_attrs_define
+class AuthOAuthExchangeBody:
+ """
+ Attributes:
+ code (str):
+ redirect_url (str):
+ """
+
+ code: str
+ redirect_url: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ code = self.code
+
+ redirect_url = self.redirect_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "code": code,
+ "redirect_url": redirect_url,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ code = d.pop("code")
+
+ redirect_url = d.pop("redirect_url")
+
+ auth_o_auth_exchange_body = cls(
+ code=code,
+ redirect_url=redirect_url,
+ )
+
+
+ auth_o_auth_exchange_body.additional_properties = d
+ return auth_o_auth_exchange_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_password_policy.py b/src/volcano_sdk/_generated/models/auth_password_policy.py
new file mode 100644
index 00000000..505b8372
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_password_policy.py
@@ -0,0 +1,116 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthPasswordPolicy")
+
+
+
+@_attrs_define
+class AuthPasswordPolicy:
+ """ Effective backend-enforced password policy.
+
+ Attributes:
+ effective_min_length (int): Effective minimum password length in Unicode characters.
+ min_configurable_length (int): Lowest minimum password length accepted by the auth configuration endpoint.
+ max_length (int): Maximum password length in Unicode characters.
+ require_uppercase (bool): Whether passwords must contain an ASCII uppercase letter (A-Z).
+ require_lowercase (bool): Whether passwords must contain an ASCII lowercase letter (a-z).
+ require_numbers (bool): Whether passwords must contain an ASCII digit (0-9).
+ require_special_chars (bool): Whether passwords must contain one of the backend-supported special characters.
+ compromised_passwords_rejected (bool): Whether common and known-compromised passwords are rejected by the
+ backend.
+ """
+
+ effective_min_length: int
+ min_configurable_length: int
+ max_length: int
+ require_uppercase: bool
+ require_lowercase: bool
+ require_numbers: bool
+ require_special_chars: bool
+ compromised_passwords_rejected: bool
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ effective_min_length = self.effective_min_length
+
+ min_configurable_length = self.min_configurable_length
+
+ max_length = self.max_length
+
+ require_uppercase = self.require_uppercase
+
+ require_lowercase = self.require_lowercase
+
+ require_numbers = self.require_numbers
+
+ require_special_chars = self.require_special_chars
+
+ compromised_passwords_rejected = self.compromised_passwords_rejected
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "effective_min_length": effective_min_length,
+ "min_configurable_length": min_configurable_length,
+ "max_length": max_length,
+ "require_uppercase": require_uppercase,
+ "require_lowercase": require_lowercase,
+ "require_numbers": require_numbers,
+ "require_special_chars": require_special_chars,
+ "compromised_passwords_rejected": compromised_passwords_rejected,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ effective_min_length = d.pop("effective_min_length")
+
+ min_configurable_length = d.pop("min_configurable_length")
+
+ max_length = d.pop("max_length")
+
+ require_uppercase = d.pop("require_uppercase")
+
+ require_lowercase = d.pop("require_lowercase")
+
+ require_numbers = d.pop("require_numbers")
+
+ require_special_chars = d.pop("require_special_chars")
+
+ compromised_passwords_rejected = d.pop("compromised_passwords_rejected")
+
+ auth_password_policy = cls(
+ effective_min_length=effective_min_length,
+ min_configurable_length=min_configurable_length,
+ max_length=max_length,
+ require_uppercase=require_uppercase,
+ require_lowercase=require_lowercase,
+ require_numbers=require_numbers,
+ require_special_chars=require_special_chars,
+ compromised_passwords_rejected=compromised_passwords_rejected,
+ )
+
+ return auth_password_policy
+
diff --git a/src/volcano_sdk/_generated/models/auth_platform_exchange_body.py b/src/volcano_sdk/_generated/models/auth_platform_exchange_body.py
new file mode 100644
index 00000000..be3f3942
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_platform_exchange_body.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthPlatformExchangeBody")
+
+
+
+@_attrs_define
+class AuthPlatformExchangeBody:
+ """
+ Attributes:
+ client_id (str):
+ """
+
+ client_id: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ client_id = self.client_id
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "client_id": client_id,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ client_id = d.pop("client_id")
+
+ auth_platform_exchange_body = cls(
+ client_id=client_id,
+ )
+
+
+ auth_platform_exchange_body.additional_properties = d
+ return auth_platform_exchange_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_refresh_body.py b/src/volcano_sdk/_generated/models/auth_refresh_body.py
new file mode 100644
index 00000000..3fb76c47
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_refresh_body.py
@@ -0,0 +1,101 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_refresh_body_session_mode import AuthRefreshBodySessionMode
+from ..models.auth_refresh_body_session_mode import check_auth_refresh_body_session_mode
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthRefreshBody")
+
+
+
+@_attrs_define
+class AuthRefreshBody:
+ """
+ Attributes:
+ refresh_token (str | Unset):
+ session_mode (AuthRefreshBodySessionMode | Unset):
+ """
+
+ refresh_token: str | Unset = UNSET
+ session_mode: AuthRefreshBodySessionMode | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ refresh_token = self.refresh_token
+
+ session_mode: str | Unset = UNSET
+ if not isinstance(self.session_mode, Unset):
+ session_mode = self.session_mode
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if refresh_token is not UNSET:
+ field_dict["refresh_token"] = refresh_token
+ if session_mode is not UNSET:
+ field_dict["session_mode"] = session_mode
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ refresh_token = d.pop("refresh_token", UNSET)
+
+ _session_mode = d.pop("session_mode", UNSET)
+ session_mode: AuthRefreshBodySessionMode | Unset
+ if isinstance(_session_mode, Unset):
+ session_mode = UNSET
+ else:
+ session_mode = check_auth_refresh_body_session_mode(_session_mode)
+
+
+
+
+ auth_refresh_body = cls(
+ refresh_token=refresh_token,
+ session_mode=session_mode,
+ )
+
+
+ auth_refresh_body.additional_properties = d
+ return auth_refresh_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_refresh_body_session_mode.py b/src/volcano_sdk/_generated/models/auth_refresh_body_session_mode.py
new file mode 100644
index 00000000..3a8b40a8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_refresh_body_session_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthRefreshBodySessionMode = Literal['cookie']
+
+AUTH_REFRESH_BODY_SESSION_MODE_VALUES: set[AuthRefreshBodySessionMode] = { 'cookie', }
+
+def check_auth_refresh_body_session_mode(value: str) -> AuthRefreshBodySessionMode:
+ if value in AUTH_REFRESH_BODY_SESSION_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_REFRESH_BODY_SESSION_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_request_email_change_body.py b/src/volcano_sdk/_generated/models/auth_request_email_change_body.py
new file mode 100644
index 00000000..e6df4161
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_request_email_change_body.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthRequestEmailChangeBody")
+
+
+
+@_attrs_define
+class AuthRequestEmailChangeBody:
+ """
+ Attributes:
+ new_email (str):
+ """
+
+ new_email: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ new_email = self.new_email
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "new_email": new_email,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ new_email = d.pop("new_email")
+
+ auth_request_email_change_body = cls(
+ new_email=new_email,
+ )
+
+
+ auth_request_email_change_body.additional_properties = d
+ return auth_request_email_change_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_request_email_change_response_200.py b/src/volcano_sdk/_generated/models/auth_request_email_change_response_200.py
new file mode 100644
index 00000000..6d9aa465
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_request_email_change_response_200.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthRequestEmailChangeResponse200")
+
+
+
+@_attrs_define
+class AuthRequestEmailChangeResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ new_email (str | Unset):
+ """
+
+ message: str | Unset = UNSET
+ new_email: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+ new_email = self.new_email
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+ if new_email is not UNSET:
+ field_dict["new_email"] = new_email
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ new_email = d.pop("new_email", UNSET)
+
+ auth_request_email_change_response_200 = cls(
+ message=message,
+ new_email=new_email,
+ )
+
+
+ auth_request_email_change_response_200.additional_properties = d
+ return auth_request_email_change_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_resend_confirmation_body.py b/src/volcano_sdk/_generated/models/auth_resend_confirmation_body.py
new file mode 100644
index 00000000..4a830907
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_resend_confirmation_body.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthResendConfirmationBody")
+
+
+
+@_attrs_define
+class AuthResendConfirmationBody:
+ """
+ Attributes:
+ email (str):
+ """
+
+ email: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ email = self.email
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "email": email,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ email = d.pop("email")
+
+ auth_resend_confirmation_body = cls(
+ email=email,
+ )
+
+
+ auth_resend_confirmation_body.additional_properties = d
+ return auth_resend_confirmation_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_resend_confirmation_response_200.py b/src/volcano_sdk/_generated/models/auth_resend_confirmation_response_200.py
new file mode 100644
index 00000000..e4d17e0e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_resend_confirmation_response_200.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthResendConfirmationResponse200")
+
+
+
+@_attrs_define
+class AuthResendConfirmationResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ """
+
+ message: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ auth_resend_confirmation_response_200 = cls(
+ message=message,
+ )
+
+
+ auth_resend_confirmation_response_200.additional_properties = d
+ return auth_resend_confirmation_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_reset_password_body.py b/src/volcano_sdk/_generated/models/auth_reset_password_body.py
new file mode 100644
index 00000000..2afb41c4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_reset_password_body.py
@@ -0,0 +1,85 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthResetPasswordBody")
+
+
+
+@_attrs_define
+class AuthResetPasswordBody:
+ """
+ Attributes:
+ token (str): Recovery token from forgot-password
+ new_password (str): Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ """
+
+ token: str
+ new_password: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ token = self.token
+
+ new_password = self.new_password
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "token": token,
+ "new_password": new_password,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ token = d.pop("token")
+
+ new_password = d.pop("new_password")
+
+ auth_reset_password_body = cls(
+ token=token,
+ new_password=new_password,
+ )
+
+
+ auth_reset_password_body.additional_properties = d
+ return auth_reset_password_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_reset_password_response_200.py b/src/volcano_sdk/_generated/models/auth_reset_password_response_200.py
new file mode 100644
index 00000000..b899a05f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_reset_password_response_200.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthResetPasswordResponse200")
+
+
+
+@_attrs_define
+class AuthResetPasswordResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ """
+
+ message: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ auth_reset_password_response_200 = cls(
+ message=message,
+ )
+
+
+ auth_reset_password_response_200.additional_properties = d
+ return auth_reset_password_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_session.py b/src/volcano_sdk/_generated/models/auth_session.py
new file mode 100644
index 00000000..fde0f961
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_session.py
@@ -0,0 +1,239 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_session_provider import AuthSessionProvider
+from ..models.auth_session_provider import check_auth_session_provider
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthSession")
+
+
+
+@_attrs_define
+class AuthSession:
+ """ An authentication session for a user
+
+ Attributes:
+ id (UUID): Unique session identifier
+ user_id (UUID): The user this session belongs to
+ provider (AuthSessionProvider): Authentication provider used to create this session Example: email.
+ expires_at (datetime.datetime): When this session expires
+ is_active (bool): Whether the session is currently active (not expired)
+ is_current (bool): Whether this is the session making the current request
+ user_agent (str | Unset): Browser/device user agent string Example: Mozilla/5.0 (Macintosh; Intel Mac OS X
+ 10_15_7).
+ ip_address (str | Unset): IP address of the client when the session was created Example: 192.168.1.1.
+ last_ip_address (str | Unset): IP address of the most recent activity (token refresh) Example: 192.168.1.100.
+ last_activity_at (datetime.datetime | Unset): Last activity timestamp
+ session_started_at (datetime.datetime | Unset): When the session was created
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ user_id: UUID
+ provider: AuthSessionProvider
+ expires_at: datetime.datetime
+ is_active: bool
+ is_current: bool
+ user_agent: str | Unset = UNSET
+ ip_address: str | Unset = UNSET
+ last_ip_address: str | Unset = UNSET
+ last_activity_at: datetime.datetime | Unset = UNSET
+ session_started_at: datetime.datetime | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ user_id = str(self.user_id)
+
+ provider: str = self.provider
+
+ expires_at = self.expires_at.isoformat()
+
+ is_active = self.is_active
+
+ is_current = self.is_current
+
+ user_agent = self.user_agent
+
+ ip_address = self.ip_address
+
+ last_ip_address = self.last_ip_address
+
+ last_activity_at: str | Unset = UNSET
+ if not isinstance(self.last_activity_at, Unset):
+ last_activity_at = self.last_activity_at.isoformat()
+
+ session_started_at: str | Unset = UNSET
+ if not isinstance(self.session_started_at, Unset):
+ session_started_at = self.session_started_at.isoformat()
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "user_id": user_id,
+ "provider": provider,
+ "expires_at": expires_at,
+ "is_active": is_active,
+ "is_current": is_current,
+ })
+ if user_agent is not UNSET:
+ field_dict["user_agent"] = user_agent
+ if ip_address is not UNSET:
+ field_dict["ip_address"] = ip_address
+ if last_ip_address is not UNSET:
+ field_dict["last_ip_address"] = last_ip_address
+ if last_activity_at is not UNSET:
+ field_dict["last_activity_at"] = last_activity_at
+ if session_started_at is not UNSET:
+ field_dict["session_started_at"] = session_started_at
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ user_id = UUID(d.pop("user_id"))
+
+
+
+
+ provider = check_auth_session_provider(d.pop("provider"))
+
+
+
+
+ expires_at = datetime.datetime.fromisoformat(d.pop("expires_at"))
+
+
+
+
+ is_active = d.pop("is_active")
+
+ is_current = d.pop("is_current")
+
+ user_agent = d.pop("user_agent", UNSET)
+
+ ip_address = d.pop("ip_address", UNSET)
+
+ last_ip_address = d.pop("last_ip_address", UNSET)
+
+ _last_activity_at = d.pop("last_activity_at", UNSET)
+ last_activity_at: datetime.datetime | Unset
+ if isinstance(_last_activity_at, Unset):
+ last_activity_at = UNSET
+ else:
+ last_activity_at = datetime.datetime.fromisoformat(_last_activity_at)
+
+
+
+
+ _session_started_at = d.pop("session_started_at", UNSET)
+ session_started_at: datetime.datetime | Unset
+ if isinstance(_session_started_at, Unset):
+ session_started_at = UNSET
+ else:
+ session_started_at = datetime.datetime.fromisoformat(_session_started_at)
+
+
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ auth_session = cls(
+ id=id,
+ user_id=user_id,
+ provider=provider,
+ expires_at=expires_at,
+ is_active=is_active,
+ is_current=is_current,
+ user_agent=user_agent,
+ ip_address=ip_address,
+ last_ip_address=last_ip_address,
+ last_activity_at=last_activity_at,
+ session_started_at=session_started_at,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ auth_session.additional_properties = d
+ return auth_session
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_session_provider.py b/src/volcano_sdk/_generated/models/auth_session_provider.py
new file mode 100644
index 00000000..02525746
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_session_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthSessionProvider = Literal['anonymous', 'apple', 'email', 'github', 'google', 'microsoft']
+
+AUTH_SESSION_PROVIDER_VALUES: set[AuthSessionProvider] = { 'anonymous', 'apple', 'email', 'github', 'google', 'microsoft', }
+
+def check_auth_session_provider(value: str) -> AuthSessionProvider:
+ if value in AUTH_SESSION_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_SESSION_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_signin_body.py b/src/volcano_sdk/_generated/models/auth_signin_body.py
new file mode 100644
index 00000000..516a2034
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_signin_body.py
@@ -0,0 +1,108 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_signin_body_session_mode import AuthSigninBodySessionMode
+from ..models.auth_signin_body_session_mode import check_auth_signin_body_session_mode
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthSigninBody")
+
+
+
+@_attrs_define
+class AuthSigninBody:
+ """
+ Attributes:
+ email (str):
+ password (str):
+ session_mode (AuthSigninBodySessionMode | Unset):
+ """
+
+ email: str
+ password: str
+ session_mode: AuthSigninBodySessionMode | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ email = self.email
+
+ password = self.password
+
+ session_mode: str | Unset = UNSET
+ if not isinstance(self.session_mode, Unset):
+ session_mode = self.session_mode
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "email": email,
+ "password": password,
+ })
+ if session_mode is not UNSET:
+ field_dict["session_mode"] = session_mode
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ email = d.pop("email")
+
+ password = d.pop("password")
+
+ _session_mode = d.pop("session_mode", UNSET)
+ session_mode: AuthSigninBodySessionMode | Unset
+ if isinstance(_session_mode, Unset):
+ session_mode = UNSET
+ else:
+ session_mode = check_auth_signin_body_session_mode(_session_mode)
+
+
+
+
+ auth_signin_body = cls(
+ email=email,
+ password=password,
+ session_mode=session_mode,
+ )
+
+
+ auth_signin_body.additional_properties = d
+ return auth_signin_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_signin_body_session_mode.py b/src/volcano_sdk/_generated/models/auth_signin_body_session_mode.py
new file mode 100644
index 00000000..c811026f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_signin_body_session_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthSigninBodySessionMode = Literal['cookie']
+
+AUTH_SIGNIN_BODY_SESSION_MODE_VALUES: set[AuthSigninBodySessionMode] = { 'cookie', }
+
+def check_auth_signin_body_session_mode(value: str) -> AuthSigninBodySessionMode:
+ if value in AUTH_SIGNIN_BODY_SESSION_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_SIGNIN_BODY_SESSION_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_signup_anonymous_body.py b/src/volcano_sdk/_generated/models/auth_signup_anonymous_body.py
new file mode 100644
index 00000000..440ccc90
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_signup_anonymous_body.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_signup_anonymous_body_user_metadata import AuthSignupAnonymousBodyUserMetadata
+
+
+
+
+
+T = TypeVar("T", bound="AuthSignupAnonymousBody")
+
+
+
+@_attrs_define
+class AuthSignupAnonymousBody:
+ """
+ Attributes:
+ user_metadata (AuthSignupAnonymousBodyUserMetadata | Unset): Custom user metadata (e.g., display_name,
+ avatar_url) Example: {'display_name': 'Alice', 'avatar_url': 'https://example.com/alice.jpg'}.
+ """
+
+ user_metadata: AuthSignupAnonymousBodyUserMetadata | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_signup_anonymous_body_user_metadata import AuthSignupAnonymousBodyUserMetadata
+ user_metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user_metadata, Unset):
+ user_metadata = self.user_metadata.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if user_metadata is not UNSET:
+ field_dict["user_metadata"] = user_metadata
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_signup_anonymous_body_user_metadata import AuthSignupAnonymousBodyUserMetadata
+ d = dict(src_dict)
+ _user_metadata = d.pop("user_metadata", UNSET)
+ user_metadata: AuthSignupAnonymousBodyUserMetadata | Unset
+ if isinstance(_user_metadata, Unset):
+ user_metadata = UNSET
+ else:
+ user_metadata = AuthSignupAnonymousBodyUserMetadata.from_dict(_user_metadata)
+
+
+
+
+ auth_signup_anonymous_body = cls(
+ user_metadata=user_metadata,
+ )
+
+
+ auth_signup_anonymous_body.additional_properties = d
+ return auth_signup_anonymous_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_signup_anonymous_body_user_metadata.py b/src/volcano_sdk/_generated/models/auth_signup_anonymous_body_user_metadata.py
new file mode 100644
index 00000000..33ace5f8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_signup_anonymous_body_user_metadata.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthSignupAnonymousBodyUserMetadata")
+
+
+
+@_attrs_define
+class AuthSignupAnonymousBodyUserMetadata:
+ """ Custom user metadata (e.g., display_name, avatar_url)
+
+ Example:
+ {'display_name': 'Alice', 'avatar_url': 'https://example.com/alice.jpg'}
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auth_signup_anonymous_body_user_metadata = cls(
+ )
+
+
+ auth_signup_anonymous_body_user_metadata.additional_properties = d
+ return auth_signup_anonymous_body_user_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_signup_body.py b/src/volcano_sdk/_generated/models/auth_signup_body.py
new file mode 100644
index 00000000..994cb566
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_signup_body.py
@@ -0,0 +1,110 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_signup_body_user_metadata import AuthSignupBodyUserMetadata
+
+
+
+
+
+T = TypeVar("T", bound="AuthSignupBody")
+
+
+
+@_attrs_define
+class AuthSignupBody:
+ """
+ Attributes:
+ email (str):
+ password (str): Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ user_metadata (AuthSignupBodyUserMetadata | Unset):
+ """
+
+ email: str
+ password: str
+ user_metadata: AuthSignupBodyUserMetadata | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_signup_body_user_metadata import AuthSignupBodyUserMetadata
+ email = self.email
+
+ password = self.password
+
+ user_metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user_metadata, Unset):
+ user_metadata = self.user_metadata.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "email": email,
+ "password": password,
+ })
+ if user_metadata is not UNSET:
+ field_dict["user_metadata"] = user_metadata
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_signup_body_user_metadata import AuthSignupBodyUserMetadata
+ d = dict(src_dict)
+ email = d.pop("email")
+
+ password = d.pop("password")
+
+ _user_metadata = d.pop("user_metadata", UNSET)
+ user_metadata: AuthSignupBodyUserMetadata | Unset
+ if isinstance(_user_metadata, Unset):
+ user_metadata = UNSET
+ else:
+ user_metadata = AuthSignupBodyUserMetadata.from_dict(_user_metadata)
+
+
+
+
+ auth_signup_body = cls(
+ email=email,
+ password=password,
+ user_metadata=user_metadata,
+ )
+
+
+ auth_signup_body.additional_properties = d
+ return auth_signup_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_signup_body_user_metadata.py b/src/volcano_sdk/_generated/models/auth_signup_body_user_metadata.py
new file mode 100644
index 00000000..baaa2cad
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_signup_body_user_metadata.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthSignupBodyUserMetadata")
+
+
+
+@_attrs_define
+class AuthSignupBodyUserMetadata:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auth_signup_body_user_metadata = cls(
+ )
+
+
+ auth_signup_body_user_metadata.additional_properties = d
+ return auth_signup_body_user_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_signup_response.py b/src/volcano_sdk/_generated/models/auth_signup_response.py
new file mode 100644
index 00000000..885e1232
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_signup_response.py
@@ -0,0 +1,90 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthSignupResponse")
+
+
+
+@_attrs_define
+class AuthSignupResponse:
+ """ Uniform, session-less response returned by POST /auth/signup. It carries no
+ tokens and no user object, and is identical for a new account and for an
+ already-registered email (anti-enumeration). Clients obtain a session with a
+ subsequent POST /auth/signin.
+
+ Attributes:
+ confirmation_required (bool): Whether the project requires email confirmation. Reflects project config
+ only (identical for a new and an existing email), so it leaks nothing about
+ account existence.
+ message (str): Human-readable acknowledgement.
+ """
+
+ confirmation_required: bool
+ message: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ confirmation_required = self.confirmation_required
+
+ message = self.message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "confirmation_required": confirmation_required,
+ "message": message,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ confirmation_required = d.pop("confirmation_required")
+
+ message = d.pop("message")
+
+ auth_signup_response = cls(
+ confirmation_required=confirmation_required,
+ message=message,
+ )
+
+
+ auth_signup_response.additional_properties = d
+ return auth_signup_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_token_response.py b/src/volcano_sdk/_generated/models/auth_token_response.py
new file mode 100644
index 00000000..8c101f58
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_token_response.py
@@ -0,0 +1,119 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_user import AuthUser
+
+
+
+
+
+T = TypeVar("T", bound="AuthTokenResponse")
+
+
+
+@_attrs_define
+class AuthTokenResponse:
+ """
+ Attributes:
+ access_token (str): JWT access token (expires after configured lifetime)
+ token_type (str): Example: bearer.
+ expires_in (int): Access token lifetime in seconds
+ user (AuthUser):
+ refresh_token (str | Unset): Long-lived token for getting new access tokens. Omitted when the
+ request uses eligible HttpOnly cookie session storage.
+ """
+
+ access_token: str
+ token_type: str
+ expires_in: int
+ user: AuthUser
+ refresh_token: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_user import AuthUser
+ access_token = self.access_token
+
+ token_type = self.token_type
+
+ expires_in = self.expires_in
+
+ user = self.user.to_dict()
+
+ refresh_token = self.refresh_token
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "access_token": access_token,
+ "token_type": token_type,
+ "expires_in": expires_in,
+ "user": user,
+ })
+ if refresh_token is not UNSET:
+ field_dict["refresh_token"] = refresh_token
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_user import AuthUser
+ d = dict(src_dict)
+ access_token = d.pop("access_token")
+
+ token_type = d.pop("token_type")
+
+ expires_in = d.pop("expires_in")
+
+ user = AuthUser.from_dict(d.pop("user"))
+
+
+
+
+ refresh_token = d.pop("refresh_token", UNSET)
+
+ auth_token_response = cls(
+ access_token=access_token,
+ token_type=token_type,
+ expires_in=expires_in,
+ user=user,
+ refresh_token=refresh_token,
+ )
+
+
+ auth_token_response.additional_properties = d
+ return auth_token_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_unlink_o_auth_provider_provider.py b/src/volcano_sdk/_generated/models/auth_unlink_o_auth_provider_provider.py
new file mode 100644
index 00000000..654a81e0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_unlink_o_auth_provider_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthUnlinkOAuthProviderProvider = Literal['apple', 'github', 'google', 'microsoft']
+
+AUTH_UNLINK_O_AUTH_PROVIDER_PROVIDER_VALUES: set[AuthUnlinkOAuthProviderProvider] = { 'apple', 'github', 'google', 'microsoft', }
+
+def check_auth_unlink_o_auth_provider_provider(value: str) -> AuthUnlinkOAuthProviderProvider:
+ if value in AUTH_UNLINK_O_AUTH_PROVIDER_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_UNLINK_O_AUTH_PROVIDER_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_update_user_body.py b/src/volcano_sdk/_generated/models/auth_update_user_body.py
new file mode 100644
index 00000000..ba45592c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_update_user_body.py
@@ -0,0 +1,105 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_update_user_body_user_metadata import AuthUpdateUserBodyUserMetadata
+
+
+
+
+
+T = TypeVar("T", bound="AuthUpdateUserBody")
+
+
+
+@_attrs_define
+class AuthUpdateUserBody:
+ """
+ Attributes:
+ password (str | Unset): Password validated after NFC normalization against the
+ policy returned by GET /auth/password-policy.
+ user_metadata (AuthUpdateUserBodyUserMetadata | Unset): Metadata keys to merge into the current user metadata.
+ Omitted keys remain unchanged; set a key to null to remove it.
+ Merging is shallow; nested objects replace the stored value for that top-level key.
+ """
+
+ password: str | Unset = UNSET
+ user_metadata: AuthUpdateUserBodyUserMetadata | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_update_user_body_user_metadata import AuthUpdateUserBodyUserMetadata
+ password = self.password
+
+ user_metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user_metadata, Unset):
+ user_metadata = self.user_metadata.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if password is not UNSET:
+ field_dict["password"] = password
+ if user_metadata is not UNSET:
+ field_dict["user_metadata"] = user_metadata
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_update_user_body_user_metadata import AuthUpdateUserBodyUserMetadata
+ d = dict(src_dict)
+ password = d.pop("password", UNSET)
+
+ _user_metadata = d.pop("user_metadata", UNSET)
+ user_metadata: AuthUpdateUserBodyUserMetadata | Unset
+ if isinstance(_user_metadata, Unset):
+ user_metadata = UNSET
+ else:
+ user_metadata = AuthUpdateUserBodyUserMetadata.from_dict(_user_metadata)
+
+
+
+
+ auth_update_user_body = cls(
+ password=password,
+ user_metadata=user_metadata,
+ )
+
+
+ auth_update_user_body.additional_properties = d
+ return auth_update_user_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_update_user_body_user_metadata.py b/src/volcano_sdk/_generated/models/auth_update_user_body_user_metadata.py
new file mode 100644
index 00000000..fbaa7acc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_update_user_body_user_metadata.py
@@ -0,0 +1,68 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthUpdateUserBodyUserMetadata")
+
+
+
+@_attrs_define
+class AuthUpdateUserBodyUserMetadata:
+ """ Metadata keys to merge into the current user metadata.
+ Omitted keys remain unchanged; set a key to null to remove it.
+ Merging is shallow; nested objects replace the stored value for that top-level key.
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auth_update_user_body_user_metadata = cls(
+ )
+
+
+ auth_update_user_body_user_metadata.additional_properties = d
+ return auth_update_user_body_user_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_update_user_response_200.py b/src/volcano_sdk/_generated/models/auth_update_user_response_200.py
new file mode 100644
index 00000000..30764b2c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_update_user_response_200.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_user import AuthUser
+
+
+
+
+
+T = TypeVar("T", bound="AuthUpdateUserResponse200")
+
+
+
+@_attrs_define
+class AuthUpdateUserResponse200:
+ """
+ Attributes:
+ user (AuthUser | Unset):
+ """
+
+ user: AuthUser | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_user import AuthUser
+ user: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user, Unset):
+ user = self.user.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if user is not UNSET:
+ field_dict["user"] = user
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_user import AuthUser
+ d = dict(src_dict)
+ _user = d.pop("user", UNSET)
+ user: AuthUser | Unset
+ if isinstance(_user, Unset):
+ user = UNSET
+ else:
+ user = AuthUser.from_dict(_user)
+
+
+
+
+ auth_update_user_response_200 = cls(
+ user=user,
+ )
+
+
+ auth_update_user_response_200.additional_properties = d
+ return auth_update_user_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_user.py b/src/volcano_sdk/_generated/models/auth_user.py
new file mode 100644
index 00000000..61261d26
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_user.py
@@ -0,0 +1,276 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.auth_user_status import AuthUserStatus
+from ..models.auth_user_status import check_auth_user_status
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.auth_user_app_metadata import AuthUserAppMetadata
+ from ..models.auth_user_user_metadata import AuthUserUserMetadata
+
+
+
+
+
+T = TypeVar("T", bound="AuthUser")
+
+
+
+@_attrs_define
+class AuthUser:
+ """
+ Attributes:
+ id (UUID):
+ email (str):
+ status (AuthUserStatus):
+ project_id (UUID | Unset):
+ email_confirmed (bool | Unset):
+ user_metadata (AuthUserUserMetadata | Unset): User-editable metadata
+ app_metadata (AuthUserAppMetadata | Unset): Application-controlled metadata (read-only for users)
+ avatar_url (str | Unset): User avatar URL (from OAuth provider or manually set)
+ banned_until (datetime.datetime | None | Unset): When temporary ban expires (null if not banned or permanent)
+ last_sign_in_at (datetime.datetime | Unset):
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ email: str
+ status: AuthUserStatus
+ project_id: UUID | Unset = UNSET
+ email_confirmed: bool | Unset = UNSET
+ user_metadata: AuthUserUserMetadata | Unset = UNSET
+ app_metadata: AuthUserAppMetadata | Unset = UNSET
+ avatar_url: str | Unset = UNSET
+ banned_until: datetime.datetime | None | Unset = UNSET
+ last_sign_in_at: datetime.datetime | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_user_app_metadata import AuthUserAppMetadata
+ from ..models.auth_user_user_metadata import AuthUserUserMetadata
+ id = str(self.id)
+
+ email = self.email
+
+ status: str = self.status
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ email_confirmed = self.email_confirmed
+
+ user_metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.user_metadata, Unset):
+ user_metadata = self.user_metadata.to_dict()
+
+ app_metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.app_metadata, Unset):
+ app_metadata = self.app_metadata.to_dict()
+
+ avatar_url = self.avatar_url
+
+ banned_until: None | str | Unset
+ if isinstance(self.banned_until, Unset):
+ banned_until = UNSET
+ elif isinstance(self.banned_until, datetime.datetime):
+ banned_until = self.banned_until.isoformat()
+ else:
+ banned_until = self.banned_until
+
+ last_sign_in_at: str | Unset = UNSET
+ if not isinstance(self.last_sign_in_at, Unset):
+ last_sign_in_at = self.last_sign_in_at.isoformat()
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "email": email,
+ "status": status,
+ })
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if email_confirmed is not UNSET:
+ field_dict["email_confirmed"] = email_confirmed
+ if user_metadata is not UNSET:
+ field_dict["user_metadata"] = user_metadata
+ if app_metadata is not UNSET:
+ field_dict["app_metadata"] = app_metadata
+ if avatar_url is not UNSET:
+ field_dict["avatar_url"] = avatar_url
+ if banned_until is not UNSET:
+ field_dict["banned_until"] = banned_until
+ if last_sign_in_at is not UNSET:
+ field_dict["last_sign_in_at"] = last_sign_in_at
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_user_app_metadata import AuthUserAppMetadata
+ from ..models.auth_user_user_metadata import AuthUserUserMetadata
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ email = d.pop("email")
+
+ status = check_auth_user_status(d.pop("status"))
+
+
+
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ email_confirmed = d.pop("email_confirmed", UNSET)
+
+ _user_metadata = d.pop("user_metadata", UNSET)
+ user_metadata: AuthUserUserMetadata | Unset
+ if isinstance(_user_metadata, Unset):
+ user_metadata = UNSET
+ else:
+ user_metadata = AuthUserUserMetadata.from_dict(_user_metadata)
+
+
+
+
+ _app_metadata = d.pop("app_metadata", UNSET)
+ app_metadata: AuthUserAppMetadata | Unset
+ if isinstance(_app_metadata, Unset):
+ app_metadata = UNSET
+ else:
+ app_metadata = AuthUserAppMetadata.from_dict(_app_metadata)
+
+
+
+
+ avatar_url = d.pop("avatar_url", UNSET)
+
+ def _parse_banned_until(data: object) -> datetime.datetime | None | Unset:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ try:
+ if not isinstance(data, str):
+ raise TypeError()
+ banned_until_type_0 = datetime.datetime.fromisoformat(data)
+
+
+
+ return banned_until_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(datetime.datetime | None | Unset, data)
+
+ banned_until = _parse_banned_until(d.pop("banned_until", UNSET))
+
+
+ _last_sign_in_at = d.pop("last_sign_in_at", UNSET)
+ last_sign_in_at: datetime.datetime | Unset
+ if isinstance(_last_sign_in_at, Unset):
+ last_sign_in_at = UNSET
+ else:
+ last_sign_in_at = datetime.datetime.fromisoformat(_last_sign_in_at)
+
+
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ auth_user = cls(
+ id=id,
+ email=email,
+ status=status,
+ project_id=project_id,
+ email_confirmed=email_confirmed,
+ user_metadata=user_metadata,
+ app_metadata=app_metadata,
+ avatar_url=avatar_url,
+ banned_until=banned_until,
+ last_sign_in_at=last_sign_in_at,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ auth_user.additional_properties = d
+ return auth_user
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_user_app_metadata.py b/src/volcano_sdk/_generated/models/auth_user_app_metadata.py
new file mode 100644
index 00000000..cf1703af
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_user_app_metadata.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthUserAppMetadata")
+
+
+
+@_attrs_define
+class AuthUserAppMetadata:
+ """ Application-controlled metadata (read-only for users)
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auth_user_app_metadata = cls(
+ )
+
+
+ auth_user_app_metadata.additional_properties = d
+ return auth_user_app_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/auth_user_status.py b/src/volcano_sdk/_generated/models/auth_user_status.py
new file mode 100644
index 00000000..cf0aed49
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_user_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+AuthUserStatus = Literal['active', 'banned', 'deleted']
+
+AUTH_USER_STATUS_VALUES: set[AuthUserStatus] = { 'active', 'banned', 'deleted', }
+
+def check_auth_user_status(value: str) -> AuthUserStatus:
+ if value in AUTH_USER_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {AUTH_USER_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/auth_user_user_metadata.py b/src/volcano_sdk/_generated/models/auth_user_user_metadata.py
new file mode 100644
index 00000000..2a16918c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/auth_user_user_metadata.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="AuthUserUserMetadata")
+
+
+
+@_attrs_define
+class AuthUserUserMetadata:
+ """ User-editable metadata
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auth_user_user_metadata = cls(
+ )
+
+
+ auth_user_user_metadata.additional_properties = d
+ return auth_user_user_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/ban_auth_user_body.py b/src/volcano_sdk/_generated/models/ban_auth_user_body.py
new file mode 100644
index 00000000..747a86a4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/ban_auth_user_body.py
@@ -0,0 +1,91 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="BanAuthUserBody")
+
+
+
+@_attrs_define
+class BanAuthUserBody:
+ """
+ Attributes:
+ banned_until (datetime.datetime | Unset): When the ban expires (omit for permanent ban) Example:
+ 2026-12-31T23:59:59Z.
+ """
+
+ banned_until: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ banned_until: str | Unset = UNSET
+ if not isinstance(self.banned_until, Unset):
+ banned_until = self.banned_until.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if banned_until is not UNSET:
+ field_dict["banned_until"] = banned_until
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ _banned_until = d.pop("banned_until", UNSET)
+ banned_until: datetime.datetime | Unset
+ if isinstance(_banned_until, Unset):
+ banned_until = UNSET
+ else:
+ banned_until = datetime.datetime.fromisoformat(_banned_until)
+
+
+
+
+ ban_auth_user_body = cls(
+ banned_until=banned_until,
+ )
+
+
+ ban_auth_user_body.additional_properties = d
+ return ban_auth_user_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/ban_user_response.py b/src/volcano_sdk/_generated/models/ban_user_response.py
new file mode 100644
index 00000000..7ec0bb21
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/ban_user_response.py
@@ -0,0 +1,146 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.ban_user_response_status import BanUserResponseStatus
+from ..models.ban_user_response_status import check_ban_user_response_status
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="BanUserResponse")
+
+
+
+@_attrs_define
+class BanUserResponse:
+ """ Response when banning a user
+
+ Attributes:
+ message (str): Example: User banned until 2026-12-31T23:59:59Z.
+ user_id (UUID):
+ email (str):
+ status (BanUserResponseStatus):
+ banned_until (datetime.datetime | None | Unset): When the ban expires (null for permanent ban)
+ """
+
+ message: str
+ user_id: UUID
+ email: str
+ status: BanUserResponseStatus
+ banned_until: datetime.datetime | None | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+ user_id = str(self.user_id)
+
+ email = self.email
+
+ status: str = self.status
+
+ banned_until: None | str | Unset
+ if isinstance(self.banned_until, Unset):
+ banned_until = UNSET
+ elif isinstance(self.banned_until, datetime.datetime):
+ banned_until = self.banned_until.isoformat()
+ else:
+ banned_until = self.banned_until
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "message": message,
+ "user_id": user_id,
+ "email": email,
+ "status": status,
+ })
+ if banned_until is not UNSET:
+ field_dict["banned_until"] = banned_until
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message")
+
+ user_id = UUID(d.pop("user_id"))
+
+
+
+
+ email = d.pop("email")
+
+ status = check_ban_user_response_status(d.pop("status"))
+
+
+
+
+ def _parse_banned_until(data: object) -> datetime.datetime | None | Unset:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ try:
+ if not isinstance(data, str):
+ raise TypeError()
+ banned_until_type_0 = datetime.datetime.fromisoformat(data)
+
+
+
+ return banned_until_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(datetime.datetime | None | Unset, data)
+
+ banned_until = _parse_banned_until(d.pop("banned_until", UNSET))
+
+
+ ban_user_response = cls(
+ message=message,
+ user_id=user_id,
+ email=email,
+ status=status,
+ banned_until=banned_until,
+ )
+
+
+ ban_user_response.additional_properties = d
+ return ban_user_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/ban_user_response_status.py b/src/volcano_sdk/_generated/models/ban_user_response_status.py
new file mode 100644
index 00000000..188423fb
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/ban_user_response_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+BanUserResponseStatus = Literal['banned']
+
+BAN_USER_RESPONSE_STATUS_VALUES: set[BanUserResponseStatus] = { 'banned', }
+
+def check_ban_user_response_status(value: str) -> BanUserResponseStatus:
+ if value in BAN_USER_RESPONSE_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {BAN_USER_RESPONSE_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/batch_function_deploy_failure.py b/src/volcano_sdk/_generated/models/batch_function_deploy_failure.py
new file mode 100644
index 00000000..70408137
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/batch_function_deploy_failure.py
@@ -0,0 +1,128 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.batch_function_deploy_failure_operation import BatchFunctionDeployFailureOperation
+from ..models.batch_function_deploy_failure_operation import check_batch_function_deploy_failure_operation
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="BatchFunctionDeployFailure")
+
+
+
+@_attrs_define
+class BatchFunctionDeployFailure:
+ """
+ Attributes:
+ name (str):
+ error (str):
+ function_id (UUID | Unset):
+ operation (BatchFunctionDeployFailureOperation | Unset):
+ """
+
+ name: str
+ error: str
+ function_id: UUID | Unset = UNSET
+ operation: BatchFunctionDeployFailureOperation | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ error = self.error
+
+ function_id: str | Unset = UNSET
+ if not isinstance(self.function_id, Unset):
+ function_id = str(self.function_id)
+
+ operation: str | Unset = UNSET
+ if not isinstance(self.operation, Unset):
+ operation = self.operation
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "error": error,
+ })
+ if function_id is not UNSET:
+ field_dict["function_id"] = function_id
+ if operation is not UNSET:
+ field_dict["operation"] = operation
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ error = d.pop("error")
+
+ _function_id = d.pop("function_id", UNSET)
+ function_id: UUID | Unset
+ if isinstance(_function_id, Unset):
+ function_id = UNSET
+ else:
+ function_id = UUID(_function_id)
+
+
+
+
+ _operation = d.pop("operation", UNSET)
+ operation: BatchFunctionDeployFailureOperation | Unset
+ if isinstance(_operation, Unset):
+ operation = UNSET
+ else:
+ operation = check_batch_function_deploy_failure_operation(_operation)
+
+
+
+
+ batch_function_deploy_failure = cls(
+ name=name,
+ error=error,
+ function_id=function_id,
+ operation=operation,
+ )
+
+
+ batch_function_deploy_failure.additional_properties = d
+ return batch_function_deploy_failure
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/batch_function_deploy_failure_operation.py b/src/volcano_sdk/_generated/models/batch_function_deploy_failure_operation.py
new file mode 100644
index 00000000..cbf51f07
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/batch_function_deploy_failure_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+BatchFunctionDeployFailureOperation = Literal['deploy', 'update']
+
+BATCH_FUNCTION_DEPLOY_FAILURE_OPERATION_VALUES: set[BatchFunctionDeployFailureOperation] = { 'deploy', 'update', }
+
+def check_batch_function_deploy_failure_operation(value: str) -> BatchFunctionDeployFailureOperation:
+ if value in BATCH_FUNCTION_DEPLOY_FAILURE_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {BATCH_FUNCTION_DEPLOY_FAILURE_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/batch_function_deploy_response.py b/src/volcano_sdk/_generated/models/batch_function_deploy_response.py
new file mode 100644
index 00000000..3b2a6b26
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/batch_function_deploy_response.py
@@ -0,0 +1,138 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+if TYPE_CHECKING:
+ from ..models.batch_function_deploy_failure import BatchFunctionDeployFailure
+ from ..models.function import Function
+
+
+
+
+
+T = TypeVar("T", bound="BatchFunctionDeployResponse")
+
+
+
+@_attrs_define
+class BatchFunctionDeployResponse:
+ """
+ Attributes:
+ batch_id (UUID):
+ data (list[Function]): Functions whose deployment workflows were started successfully
+ failed (list[BatchFunctionDeployFailure] | Unset): Functions that failed before their workflow started.
+ Successful functions are left running; failed new functions are deleted and failed updates are rolled back where
+ possible.
+ """
+
+ batch_id: UUID
+ data: list[Function]
+ failed: list[BatchFunctionDeployFailure] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.batch_function_deploy_failure import BatchFunctionDeployFailure
+ from ..models.function import Function
+ batch_id = str(self.batch_id)
+
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ failed: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.failed, Unset):
+ failed = []
+ for failed_item_data in self.failed:
+ failed_item = failed_item_data.to_dict()
+ failed.append(failed_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "batch_id": batch_id,
+ "data": data,
+ })
+ if failed is not UNSET:
+ field_dict["failed"] = failed
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.batch_function_deploy_failure import BatchFunctionDeployFailure
+ from ..models.function import Function
+ d = dict(src_dict)
+ batch_id = UUID(d.pop("batch_id"))
+
+
+
+
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = Function.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ _failed = d.pop("failed", UNSET)
+ failed: list[BatchFunctionDeployFailure] | Unset = UNSET
+ if _failed is not UNSET:
+ failed = []
+ for failed_item_data in _failed:
+ failed_item = BatchFunctionDeployFailure.from_dict(failed_item_data)
+
+
+
+ failed.append(failed_item)
+
+
+ batch_function_deploy_response = cls(
+ batch_id=batch_id,
+ data=data,
+ failed=failed,
+ )
+
+
+ batch_function_deploy_response.additional_properties = d
+ return batch_function_deploy_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body.py b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body.py
new file mode 100644
index 00000000..d87986a1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body.py
@@ -0,0 +1,126 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.call_o_auth_provider_api_body_method import CallOAuthProviderAPIBodyMethod
+from ..models.call_o_auth_provider_api_body_method import check_call_o_auth_provider_api_body_method
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.call_o_auth_provider_api_body_body import CallOAuthProviderAPIBodyBody
+
+
+
+
+
+T = TypeVar("T", bound="CallOAuthProviderAPIBody")
+
+
+
+@_attrs_define
+class CallOAuthProviderAPIBody:
+ """
+ Attributes:
+ endpoint (str): Relative path on the provider's API, beginning with `/`. It is
+ joined with the provider's fixed base URL; it must not contain a
+ scheme, host, userinfo, or a leading `//`.
+ Example: /user/repos.
+ method (CallOAuthProviderAPIBodyMethod | Unset): HTTP method to use Default: 'GET'.
+ body (CallOAuthProviderAPIBodyBody | Unset): Request body for POST requests
+ """
+
+ endpoint: str
+ method: CallOAuthProviderAPIBodyMethod | Unset = 'GET'
+ body: CallOAuthProviderAPIBodyBody | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.call_o_auth_provider_api_body_body import CallOAuthProviderAPIBodyBody
+ endpoint = self.endpoint
+
+ method: str | Unset = UNSET
+ if not isinstance(self.method, Unset):
+ method = self.method
+
+
+ body: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.body, Unset):
+ body = self.body.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "endpoint": endpoint,
+ })
+ if method is not UNSET:
+ field_dict["method"] = method
+ if body is not UNSET:
+ field_dict["body"] = body
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.call_o_auth_provider_api_body_body import CallOAuthProviderAPIBodyBody
+ d = dict(src_dict)
+ endpoint = d.pop("endpoint")
+
+ _method = d.pop("method", UNSET)
+ method: CallOAuthProviderAPIBodyMethod | Unset
+ if isinstance(_method, Unset):
+ method = UNSET
+ else:
+ method = check_call_o_auth_provider_api_body_method(_method)
+
+
+
+
+ _body = d.pop("body", UNSET)
+ body: CallOAuthProviderAPIBodyBody | Unset
+ if isinstance(_body, Unset):
+ body = UNSET
+ else:
+ body = CallOAuthProviderAPIBodyBody.from_dict(_body)
+
+
+
+
+ call_o_auth_provider_api_body = cls(
+ endpoint=endpoint,
+ method=method,
+ body=body,
+ )
+
+
+ call_o_auth_provider_api_body.additional_properties = d
+ return call_o_auth_provider_api_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_body.py b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_body.py
new file mode 100644
index 00000000..5e4b8ead
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_body.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="CallOAuthProviderAPIBodyBody")
+
+
+
+@_attrs_define
+class CallOAuthProviderAPIBodyBody:
+ """ Request body for POST requests
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ call_o_auth_provider_api_body_body = cls(
+ )
+
+
+ call_o_auth_provider_api_body_body.additional_properties = d
+ return call_o_auth_provider_api_body_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_method.py b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_method.py
new file mode 100644
index 00000000..8556454d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_body_method.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CallOAuthProviderAPIBodyMethod = Literal['GET', 'POST']
+
+CALL_O_AUTH_PROVIDER_API_BODY_METHOD_VALUES: set[CallOAuthProviderAPIBodyMethod] = { 'GET', 'POST', }
+
+def check_call_o_auth_provider_api_body_method(value: str) -> CallOAuthProviderAPIBodyMethod:
+ if value in CALL_O_AUTH_PROVIDER_API_BODY_METHOD_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CALL_O_AUTH_PROVIDER_API_BODY_METHOD_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/call_o_auth_provider_api_provider.py b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_provider.py
new file mode 100644
index 00000000..aecba0e0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CallOAuthProviderAPIProvider = Literal['apple', 'github', 'google', 'microsoft']
+
+CALL_O_AUTH_PROVIDER_API_PROVIDER_VALUES: set[CallOAuthProviderAPIProvider] = { 'apple', 'github', 'google', 'microsoft', }
+
+def check_call_o_auth_provider_api_provider(value: str) -> CallOAuthProviderAPIProvider:
+ if value in CALL_O_AUTH_PROVIDER_API_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CALL_O_AUTH_PROVIDER_API_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/call_o_auth_provider_api_response_200.py b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_response_200.py
new file mode 100644
index 00000000..2d2f5baf
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/call_o_auth_provider_api_response_200.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="CallOAuthProviderAPIResponse200")
+
+
+
+@_attrs_define
+class CallOAuthProviderAPIResponse200:
+ """ Raw response from the OAuth provider's API
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ call_o_auth_provider_api_response_200 = cls(
+ )
+
+
+ call_o_auth_provider_api_response_200.additional_properties = d
+ return call_o_auth_provider_api_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/complete_upload_session_response.py b/src/volcano_sdk/_generated/models/complete_upload_session_response.py
new file mode 100644
index 00000000..10030743
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/complete_upload_session_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.storage_object import StorageObject
+
+
+
+
+
+T = TypeVar("T", bound="CompleteUploadSessionResponse")
+
+
+
+@_attrs_define
+class CompleteUploadSessionResponse:
+ """ Response when completing an upload
+
+ Attributes:
+ object_ (StorageObject | Unset):
+ """
+
+ object_: StorageObject | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.storage_object import StorageObject
+ object_: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.object_, Unset):
+ object_ = self.object_.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if object_ is not UNSET:
+ field_dict["object"] = object_
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.storage_object import StorageObject
+ d = dict(src_dict)
+ _object_ = d.pop("object", UNSET)
+ object_: StorageObject | Unset
+ if isinstance(_object_, Unset):
+ object_ = UNSET
+ else:
+ object_ = StorageObject.from_dict(_object_)
+
+
+
+
+ complete_upload_session_response = cls(
+ object_=object_,
+ )
+
+
+ complete_upload_session_response.additional_properties = d
+ return complete_upload_session_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/configure_auth_methods_body.py b/src/volcano_sdk/_generated/models/configure_auth_methods_body.py
new file mode 100644
index 00000000..9cc814ee
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/configure_auth_methods_body.py
@@ -0,0 +1,118 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.configure_auth_methods_body_oauth_providers_item import ConfigureAuthMethodsBodyOauthProvidersItem
+
+
+
+
+
+T = TypeVar("T", bound="ConfigureAuthMethodsBody")
+
+
+
+@_attrs_define
+class ConfigureAuthMethodsBody:
+ """
+ Attributes:
+ enable_email_password (bool | Unset):
+ enable_anonymous (bool | Unset):
+ oauth_providers (list[ConfigureAuthMethodsBodyOauthProvidersItem] | Unset):
+ """
+
+ enable_email_password: bool | Unset = UNSET
+ enable_anonymous: bool | Unset = UNSET
+ oauth_providers: list[ConfigureAuthMethodsBodyOauthProvidersItem] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.configure_auth_methods_body_oauth_providers_item import ConfigureAuthMethodsBodyOauthProvidersItem
+ enable_email_password = self.enable_email_password
+
+ enable_anonymous = self.enable_anonymous
+
+ oauth_providers: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.oauth_providers, Unset):
+ oauth_providers = []
+ for oauth_providers_item_data in self.oauth_providers:
+ oauth_providers_item = oauth_providers_item_data.to_dict()
+ oauth_providers.append(oauth_providers_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if enable_email_password is not UNSET:
+ field_dict["enable_email_password"] = enable_email_password
+ if enable_anonymous is not UNSET:
+ field_dict["enable_anonymous"] = enable_anonymous
+ if oauth_providers is not UNSET:
+ field_dict["oauth_providers"] = oauth_providers
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.configure_auth_methods_body_oauth_providers_item import ConfigureAuthMethodsBodyOauthProvidersItem
+ d = dict(src_dict)
+ enable_email_password = d.pop("enable_email_password", UNSET)
+
+ enable_anonymous = d.pop("enable_anonymous", UNSET)
+
+ _oauth_providers = d.pop("oauth_providers", UNSET)
+ oauth_providers: list[ConfigureAuthMethodsBodyOauthProvidersItem] | Unset = UNSET
+ if _oauth_providers is not UNSET:
+ oauth_providers = []
+ for oauth_providers_item_data in _oauth_providers:
+ oauth_providers_item = ConfigureAuthMethodsBodyOauthProvidersItem.from_dict(oauth_providers_item_data)
+
+
+
+ oauth_providers.append(oauth_providers_item)
+
+
+ configure_auth_methods_body = cls(
+ enable_email_password=enable_email_password,
+ enable_anonymous=enable_anonymous,
+ oauth_providers=oauth_providers,
+ )
+
+
+ configure_auth_methods_body.additional_properties = d
+ return configure_auth_methods_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/configure_auth_methods_body_oauth_providers_item.py b/src/volcano_sdk/_generated/models/configure_auth_methods_body_oauth_providers_item.py
new file mode 100644
index 00000000..eb44fa68
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/configure_auth_methods_body_oauth_providers_item.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ConfigureAuthMethodsBodyOauthProvidersItem")
+
+
+
+@_attrs_define
+class ConfigureAuthMethodsBodyOauthProvidersItem:
+ """
+ Attributes:
+ provider (str | Unset):
+ enabled (bool | Unset):
+ """
+
+ provider: str | Unset = UNSET
+ enabled: bool | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ provider = self.provider
+
+ enabled = self.enabled
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if provider is not UNSET:
+ field_dict["provider"] = provider
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ provider = d.pop("provider", UNSET)
+
+ enabled = d.pop("enabled", UNSET)
+
+ configure_auth_methods_body_oauth_providers_item = cls(
+ provider=provider,
+ enabled=enabled,
+ )
+
+
+ configure_auth_methods_body_oauth_providers_item.additional_properties = d
+ return configure_auth_methods_body_oauth_providers_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/connect_project_git_request.py b/src/volcano_sdk/_generated/models/connect_project_git_request.py
new file mode 100644
index 00000000..63fefff6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/connect_project_git_request.py
@@ -0,0 +1,137 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ConnectProjectGitRequest")
+
+
+
+@_attrs_define
+class ConnectProjectGitRequest:
+ """
+ Attributes:
+ connection_id (UUID): The caller's user_git_connections row (see /user/git/connections).
+ installation_id (int):
+ repository_id (int | Unset): Stable GitHub repository id (repository.id), the preferred selector. Either
+ repository_id or repo_full_name is required; when both are given they must identify the same live repository.
+ repo_full_name (str | Unset): Deprecated selector kept for a compatibility window; prefer repository_id. Either
+ repository_id or repo_full_name is required.
+ root_directory (str | Unset): Monorepo subdirectory the project builds from. Omit for the repo root.
+ production_branch (str | Unset): The branch a push must land on to deploy, with three cases, because this is a
+ full replace and a read-modify-write client sends back whatever it read. Omit it to follow the repository's
+ GitHub default branch, which also discards a branch set earlier. Send back the branch the project already
+ deploys from, when that is the repository's default, and nothing changes either way — a project pinned to that
+ branch stays pinned. Sending the default branch when the project deploys from something else returns it to
+ following the default, including on a rebind, where a pin describes a branch chosen for the repository being
+ left. Any other branch becomes the project's own choice, exempt from later default-branch renames. Validated as
+ a Git branch name only: it does not have to exist yet, so a project can be pointed at a branch about to be
+ pushed. Changing repository and naming a branch other than the new repository's default in one request is
+ refused with 400, because the branch named is almost always the previous repository's, echoed back — connect
+ first, then set the branch.
+ """
+
+ connection_id: UUID
+ installation_id: int
+ repository_id: int | Unset = UNSET
+ repo_full_name: str | Unset = UNSET
+ root_directory: str | Unset = UNSET
+ production_branch: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ connection_id = str(self.connection_id)
+
+ installation_id = self.installation_id
+
+ repository_id = self.repository_id
+
+ repo_full_name = self.repo_full_name
+
+ root_directory = self.root_directory
+
+ production_branch = self.production_branch
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "connection_id": connection_id,
+ "installation_id": installation_id,
+ })
+ if repository_id is not UNSET:
+ field_dict["repository_id"] = repository_id
+ if repo_full_name is not UNSET:
+ field_dict["repo_full_name"] = repo_full_name
+ if root_directory is not UNSET:
+ field_dict["root_directory"] = root_directory
+ if production_branch is not UNSET:
+ field_dict["production_branch"] = production_branch
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ connection_id = UUID(d.pop("connection_id"))
+
+
+
+
+ installation_id = d.pop("installation_id")
+
+ repository_id = d.pop("repository_id", UNSET)
+
+ repo_full_name = d.pop("repo_full_name", UNSET)
+
+ root_directory = d.pop("root_directory", UNSET)
+
+ production_branch = d.pop("production_branch", UNSET)
+
+ connect_project_git_request = cls(
+ connection_id=connection_id,
+ installation_id=installation_id,
+ repository_id=repository_id,
+ repo_full_name=repo_full_name,
+ root_directory=root_directory,
+ production_branch=production_branch,
+ )
+
+
+ connect_project_git_request.additional_properties = d
+ return connect_project_git_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_anon_key_body.py b/src/volcano_sdk/_generated/models/create_anon_key_body.py
new file mode 100644
index 00000000..79e818bb
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_anon_key_body.py
@@ -0,0 +1,112 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.create_anon_key_body_permissions_item import check_create_anon_key_body_permissions_item
+from ..models.create_anon_key_body_permissions_item import CreateAnonKeyBodyPermissionsItem
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateAnonKeyBody")
+
+
+
+@_attrs_define
+class CreateAnonKeyBody:
+ """
+ Attributes:
+ name (str): Key name for identification.
+ Can only contain letters, numbers, underscores, and hyphens.
+ Example: frontend-app.
+ permissions (list[CreateAnonKeyBodyPermissionsItem] | Unset): Optional list of permissions for this key.
+ If not provided, defaults to auth-only permissions: auth.signup, auth.signin, auth.refresh, auth.logout,
+ auth.password_reset, auth.confirm_email, auth.resend_confirmation.
+ Storage, realtime, and functions permissions must be explicitly added if needed.
+ Example: ['auth.signup', 'auth.signin', 'auth.refresh', 'auth.logout'].
+ """
+
+ name: str
+ permissions: list[CreateAnonKeyBodyPermissionsItem] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ permissions: list[str] | Unset = UNSET
+ if not isinstance(self.permissions, Unset):
+ permissions = []
+ for permissions_item_data in self.permissions:
+ permissions_item: str = permissions_item_data
+ permissions.append(permissions_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ })
+ if permissions is not UNSET:
+ field_dict["permissions"] = permissions
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ _permissions = d.pop("permissions", UNSET)
+ permissions: list[CreateAnonKeyBodyPermissionsItem] | Unset = UNSET
+ if _permissions is not UNSET:
+ permissions = []
+ for permissions_item_data in _permissions:
+ permissions_item = check_create_anon_key_body_permissions_item(permissions_item_data)
+
+
+
+ permissions.append(permissions_item)
+
+
+ create_anon_key_body = cls(
+ name=name,
+ permissions=permissions,
+ )
+
+
+ create_anon_key_body.additional_properties = d
+ return create_anon_key_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_anon_key_body_permissions_item.py b/src/volcano_sdk/_generated/models/create_anon_key_body_permissions_item.py
new file mode 100644
index 00000000..f9d7b999
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_anon_key_body_permissions_item.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateAnonKeyBodyPermissionsItem = Literal['auth.confirm_email', 'auth.logout', 'auth.password_reset', 'auth.refresh', 'auth.resend_confirmation', 'auth.signin', 'auth.signup', 'functions.invoke', 'realtime.connect', 'realtime.publish', 'realtime.subscribe', 'storage.delete', 'storage.download', 'storage.list', 'storage.upload']
+
+CREATE_ANON_KEY_BODY_PERMISSIONS_ITEM_VALUES: set[CreateAnonKeyBodyPermissionsItem] = { 'auth.confirm_email', 'auth.logout', 'auth.password_reset', 'auth.refresh', 'auth.resend_confirmation', 'auth.signin', 'auth.signup', 'functions.invoke', 'realtime.connect', 'realtime.publish', 'realtime.subscribe', 'storage.delete', 'storage.download', 'storage.list', 'storage.upload', }
+
+def check_create_anon_key_body_permissions_item(value: str) -> CreateAnonKeyBodyPermissionsItem:
+ if value in CREATE_ANON_KEY_BODY_PERMISSIONS_ITEM_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_ANON_KEY_BODY_PERMISSIONS_ITEM_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_database_branch_request.py b/src/volcano_sdk/_generated/models/create_database_branch_request.py
new file mode 100644
index 00000000..785c8813
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_database_branch_request.py
@@ -0,0 +1,88 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateDatabaseBranchRequest")
+
+
+
+@_attrs_define
+class CreateDatabaseBranchRequest:
+ """
+ Attributes:
+ name (str): Branch name (must be unique within the parent database) Example: feature_checkout.
+ ttl_seconds (int | Unset): How long the branch should live, between one hour and 30 days.
+ Defaults to 7 days when omitted.
+ Example: 86400.
+ """
+
+ name: str
+ ttl_seconds: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ ttl_seconds = self.ttl_seconds
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ })
+ if ttl_seconds is not UNSET:
+ field_dict["ttl_seconds"] = ttl_seconds
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ ttl_seconds = d.pop("ttl_seconds", UNSET)
+
+ create_database_branch_request = cls(
+ name=name,
+ ttl_seconds=ttl_seconds,
+ )
+
+
+ create_database_branch_request.additional_properties = d
+ return create_database_branch_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_database_request.py b/src/volcano_sdk/_generated/models/create_database_request.py
new file mode 100644
index 00000000..48a960de
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_database_request.py
@@ -0,0 +1,134 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.create_database_request_database_type import check_create_database_request_database_type
+from ..models.create_database_request_database_type import CreateDatabaseRequestDatabaseType
+from ..models.create_database_request_pg_version import check_create_database_request_pg_version
+from ..models.create_database_request_pg_version import CreateDatabaseRequestPgVersion
+from ..models.create_database_request_region import check_create_database_request_region
+from ..models.create_database_request_region import CreateDatabaseRequestRegion
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateDatabaseRequest")
+
+
+
+@_attrs_define
+class CreateDatabaseRequest:
+ """ Create a new PostgreSQL database. Volcano automatically sets up:
+ - Auth helpers (auth.uid(), auth.email(), auth.role())
+ - Database roles (anon for unauthenticated, authenticated for signed-in users)
+ - Secure multi-tenant isolation
+ - Ready for Row-Level Security
+
+ Attributes:
+ name (str): Database name (must be unique within project) Example: my_database.
+ region (CreateDatabaseRequestRegion): Region for database hosting Example: aws-us-east-1.
+ pg_version (CreateDatabaseRequestPgVersion): PostgreSQL major version Example: 16.
+ database_type (CreateDatabaseRequestDatabaseType | Unset): Compute size tier (optional, defaults to volcano-db-
+ xs).
+ Determines autoscaling limits for the database.
+ Default: 'volcano-db-xs'. Example: volcano-db-xs.
+ """
+
+ name: str
+ region: CreateDatabaseRequestRegion
+ pg_version: CreateDatabaseRequestPgVersion
+ database_type: CreateDatabaseRequestDatabaseType | Unset = 'volcano-db-xs'
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ region: str = self.region
+
+ pg_version: str = self.pg_version
+
+ database_type: str | Unset = UNSET
+ if not isinstance(self.database_type, Unset):
+ database_type = self.database_type
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "region": region,
+ "pg_version": pg_version,
+ })
+ if database_type is not UNSET:
+ field_dict["database_type"] = database_type
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ region = check_create_database_request_region(d.pop("region"))
+
+
+
+
+ pg_version = check_create_database_request_pg_version(d.pop("pg_version"))
+
+
+
+
+ _database_type = d.pop("database_type", UNSET)
+ database_type: CreateDatabaseRequestDatabaseType | Unset
+ if isinstance(_database_type, Unset):
+ database_type = UNSET
+ else:
+ database_type = check_create_database_request_database_type(_database_type)
+
+
+
+
+ create_database_request = cls(
+ name=name,
+ region=region,
+ pg_version=pg_version,
+ database_type=database_type,
+ )
+
+
+ create_database_request.additional_properties = d
+ return create_database_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_database_request_database_type.py b/src/volcano_sdk/_generated/models/create_database_request_database_type.py
new file mode 100644
index 00000000..5afc3e64
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_database_request_database_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateDatabaseRequestDatabaseType = Literal['volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs']
+
+CREATE_DATABASE_REQUEST_DATABASE_TYPE_VALUES: set[CreateDatabaseRequestDatabaseType] = { 'volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs', }
+
+def check_create_database_request_database_type(value: str) -> CreateDatabaseRequestDatabaseType:
+ if value in CREATE_DATABASE_REQUEST_DATABASE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_DATABASE_REQUEST_DATABASE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_database_request_pg_version.py b/src/volcano_sdk/_generated/models/create_database_request_pg_version.py
new file mode 100644
index 00000000..06be0efc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_database_request_pg_version.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateDatabaseRequestPgVersion = Literal['15', '16']
+
+CREATE_DATABASE_REQUEST_PG_VERSION_VALUES: set[CreateDatabaseRequestPgVersion] = { '15', '16', }
+
+def check_create_database_request_pg_version(value: str) -> CreateDatabaseRequestPgVersion:
+ if value in CREATE_DATABASE_REQUEST_PG_VERSION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_DATABASE_REQUEST_PG_VERSION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_database_request_region.py b/src/volcano_sdk/_generated/models/create_database_request_region.py
new file mode 100644
index 00000000..9660861b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_database_request_region.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateDatabaseRequestRegion = Literal['aws-ap-southeast-1', 'aws-ap-southeast-2', 'aws-eu-central-1', 'aws-eu-west-2', 'aws-sa-east-1', 'aws-us-east-1', 'aws-us-east-2', 'aws-us-west-2']
+
+CREATE_DATABASE_REQUEST_REGION_VALUES: set[CreateDatabaseRequestRegion] = { 'aws-ap-southeast-1', 'aws-ap-southeast-2', 'aws-eu-central-1', 'aws-eu-west-2', 'aws-sa-east-1', 'aws-us-east-1', 'aws-us-east-2', 'aws-us-west-2', }
+
+def check_create_database_request_region(value: str) -> CreateDatabaseRequestRegion:
+ if value in CREATE_DATABASE_REQUEST_REGION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_DATABASE_REQUEST_REGION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_email_template_request.py b/src/volcano_sdk/_generated/models/create_email_template_request.py
new file mode 100644
index 00000000..95905f8b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_email_template_request.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.create_email_template_request_template_type import check_create_email_template_request_template_type
+from ..models.create_email_template_request_template_type import CreateEmailTemplateRequestTemplateType
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateEmailTemplateRequest")
+
+
+
+@_attrs_define
+class CreateEmailTemplateRequest:
+ """
+ Attributes:
+ template_type (CreateEmailTemplateRequestTemplateType): Type of email template
+ subject (str): Email subject line Example: Confirm your email.
+ html_body (str): HTML template body. Available placeholders:
+ - {{.Token}} - The confirmation/reset token
+ - {{.ProjectName}} - The project name
+ - {{.Email}} - User's email address
+ text_body (str): Plain text template body (same placeholders as HTML)
+ """
+
+ template_type: CreateEmailTemplateRequestTemplateType
+ subject: str
+ html_body: str
+ text_body: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ template_type: str = self.template_type
+
+ subject = self.subject
+
+ html_body = self.html_body
+
+ text_body = self.text_body
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "template_type": template_type,
+ "subject": subject,
+ "html_body": html_body,
+ "text_body": text_body,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ template_type = check_create_email_template_request_template_type(d.pop("template_type"))
+
+
+
+
+ subject = d.pop("subject")
+
+ html_body = d.pop("html_body")
+
+ text_body = d.pop("text_body")
+
+ create_email_template_request = cls(
+ template_type=template_type,
+ subject=subject,
+ html_body=html_body,
+ text_body=text_body,
+ )
+
+
+ create_email_template_request.additional_properties = d
+ return create_email_template_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_email_template_request_template_type.py b/src/volcano_sdk/_generated/models/create_email_template_request_template_type.py
new file mode 100644
index 00000000..f28848f6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_email_template_request_template_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateEmailTemplateRequestTemplateType = Literal['confirmation', 'password_changed', 'password_reset', 'welcome']
+
+CREATE_EMAIL_TEMPLATE_REQUEST_TEMPLATE_TYPE_VALUES: set[CreateEmailTemplateRequestTemplateType] = { 'confirmation', 'password_changed', 'password_reset', 'welcome', }
+
+def check_create_email_template_request_template_type(value: str) -> CreateEmailTemplateRequestTemplateType:
+ if value in CREATE_EMAIL_TEMPLATE_REQUEST_TEMPLATE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_EMAIL_TEMPLATE_REQUEST_TEMPLATE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_frontend_body.py b/src/volcano_sdk/_generated/models/create_frontend_body.py
new file mode 100644
index 00000000..28bd1cd6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_frontend_body.py
@@ -0,0 +1,159 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+import json
+from .. import types
+
+from ..types import UNSET, Unset
+
+from ..models.create_frontend_body_framework import check_create_frontend_body_framework
+from ..models.create_frontend_body_framework import CreateFrontendBodyFramework
+from ..types import File, FileTypes
+from ..types import UNSET, Unset
+from io import BytesIO
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateFrontendBody")
+
+
+
+@_attrs_define
+class CreateFrontendBody:
+ """
+ Attributes:
+ name (str): DNS-safe frontend name
+ archive (File): ZIP or tar.gz archive of the frontend project directory or monorepo workspace root. The API
+ enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz archive.
+ framework (CreateFrontendBodyFramework | Unset): Next.js frontend. Supported Next.js majors are 15.x and 16.x.
+ Default: 'nextjs'.
+ app_root (str | Unset): Optional relative POSIX path from the uploaded archive root to the Next.js app to build,
+ for example `apps/web`. Example: apps/web.
+ """
+
+ name: str
+ archive: File
+ framework: CreateFrontendBodyFramework | Unset = 'nextjs'
+ app_root: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ archive = self.archive.to_tuple()
+
+
+ framework: str | Unset = UNSET
+ if not isinstance(self.framework, Unset):
+ framework = self.framework
+
+
+ app_root = self.app_root
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "archive": archive,
+ })
+ if framework is not UNSET:
+ field_dict["framework"] = framework
+ if app_root is not UNSET:
+ field_dict["app_root"] = app_root
+
+ return field_dict
+
+
+ def to_multipart(self) -> types.RequestFiles:
+ files: types.RequestFiles = []
+
+ files.append(("name", (None, str(self.name).encode(), "text/plain")))
+
+
+
+ files.append(("archive", self.archive.to_tuple()))
+
+
+
+ if not isinstance(self.framework, Unset):
+ files.append(("framework", (None, str(self.framework).encode(), "text/plain")))
+
+
+
+ if not isinstance(self.app_root, Unset):
+ files.append(("app_root", (None, str(self.app_root).encode(), "text/plain")))
+
+
+
+
+ for prop_name, prop in self.additional_properties.items():
+ files.append((prop_name, (None, str(prop).encode(), "text/plain")))
+
+
+
+ return files
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ archive = File(
+ payload = BytesIO(d.pop("archive"))
+ )
+
+
+
+
+ _framework = d.pop("framework", UNSET)
+ framework: CreateFrontendBodyFramework | Unset
+ if isinstance(_framework, Unset):
+ framework = UNSET
+ else:
+ framework = check_create_frontend_body_framework(_framework)
+
+
+
+
+ app_root = d.pop("app_root", UNSET)
+
+ create_frontend_body = cls(
+ name=name,
+ archive=archive,
+ framework=framework,
+ app_root=app_root,
+ )
+
+
+ create_frontend_body.additional_properties = d
+ return create_frontend_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_frontend_body_framework.py b/src/volcano_sdk/_generated/models/create_frontend_body_framework.py
new file mode 100644
index 00000000..8fbfa9d4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_frontend_body_framework.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateFrontendBodyFramework = Literal['nextjs']
+
+CREATE_FRONTEND_BODY_FRAMEWORK_VALUES: set[CreateFrontendBodyFramework] = { 'nextjs', }
+
+def check_create_frontend_body_framework(value: str) -> CreateFrontendBodyFramework:
+ if value in CREATE_FRONTEND_BODY_FRAMEWORK_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_FRONTEND_BODY_FRAMEWORK_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_frontend_custom_domain_request.py b/src/volcano_sdk/_generated/models/create_frontend_custom_domain_request.py
new file mode 100644
index 00000000..12637293
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_frontend_custom_domain_request.py
@@ -0,0 +1,92 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.frontend_custom_domain_tls_config import FrontendCustomDomainTLSConfig
+
+
+
+
+
+T = TypeVar("T", bound="CreateFrontendCustomDomainRequest")
+
+
+
+@_attrs_define
+class CreateFrontendCustomDomainRequest:
+ """
+ Attributes:
+ domain (str): Fully-qualified domain name (hostname only, no scheme/path) Example: app.example.com.
+ tls (FrontendCustomDomainTLSConfig):
+ """
+
+ domain: str
+ tls: FrontendCustomDomainTLSConfig
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend_custom_domain_tls_config import FrontendCustomDomainTLSConfig
+ domain = self.domain
+
+ tls = self.tls.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "domain": domain,
+ "tls": tls,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend_custom_domain_tls_config import FrontendCustomDomainTLSConfig
+ d = dict(src_dict)
+ domain = d.pop("domain")
+
+ tls = FrontendCustomDomainTLSConfig.from_dict(d.pop("tls"))
+
+
+
+
+ create_frontend_custom_domain_request = cls(
+ domain=domain,
+ tls=tls,
+ )
+
+
+ create_frontend_custom_domain_request.additional_properties = d
+ return create_frontend_custom_domain_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_function_body.py b/src/volcano_sdk/_generated/models/create_function_body.py
new file mode 100644
index 00000000..b6dfd352
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_function_body.py
@@ -0,0 +1,157 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+import json
+from .. import types
+
+from ..types import UNSET, Unset
+
+from ..models.create_function_body_runtime import check_create_function_body_runtime
+from ..models.create_function_body_runtime import CreateFunctionBodyRuntime
+from ..types import File, FileTypes
+from ..types import UNSET, Unset
+from io import BytesIO
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateFunctionBody")
+
+
+
+@_attrs_define
+class CreateFunctionBody:
+ """
+ Attributes:
+ name (str): DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen)
+ Example: my-api-function.
+ code (File): ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. The API
+ enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz source archive.
+ runtime (CreateFunctionBodyRuntime): Runtime environment. Required.
+ - Node.js: nodejs22.x, nodejs24.x
+ - Python: python3.10, python3.11, python3.12, python3.13, python3.14
+ - Ruby: ruby3.3, ruby3.4, ruby4.0
+ Example: nodejs24.x.
+ handler (str | Unset): The name of the function to invoke. Defaults to "handler" if not specified.
+ Your code must export/define a function with this name:
+ - Node.js: exports.handler (in index.js)
+ - Python: def handler() (in main.py)
+ - Ruby: def handler() (in main.rb)
+ Default: 'handler'. Example: handler.
+ """
+
+ name: str
+ code: File
+ runtime: CreateFunctionBodyRuntime
+ handler: str | Unset = 'handler'
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ code = self.code.to_tuple()
+
+
+ runtime: str = self.runtime
+
+ handler = self.handler
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "code": code,
+ "runtime": runtime,
+ })
+ if handler is not UNSET:
+ field_dict["handler"] = handler
+
+ return field_dict
+
+
+ def to_multipart(self) -> types.RequestFiles:
+ files: types.RequestFiles = []
+
+ files.append(("name", (None, str(self.name).encode(), "text/plain")))
+
+
+
+ files.append(("code", self.code.to_tuple()))
+
+
+
+ files.append(("runtime", (None, str(self.runtime).encode(), "text/plain")))
+
+
+
+ if not isinstance(self.handler, Unset):
+ files.append(("handler", (None, str(self.handler).encode(), "text/plain")))
+
+
+
+
+ for prop_name, prop in self.additional_properties.items():
+ files.append((prop_name, (None, str(prop).encode(), "text/plain")))
+
+
+
+ return files
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ code = File(
+ payload = BytesIO(d.pop("code"))
+ )
+
+
+
+
+ runtime = check_create_function_body_runtime(d.pop("runtime"))
+
+
+
+
+ handler = d.pop("handler", UNSET)
+
+ create_function_body = cls(
+ name=name,
+ code=code,
+ runtime=runtime,
+ handler=handler,
+ )
+
+
+ create_function_body.additional_properties = d
+ return create_function_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_function_body_runtime.py b/src/volcano_sdk/_generated/models/create_function_body_runtime.py
new file mode 100644
index 00000000..e4160834
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_function_body_runtime.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateFunctionBodyRuntime = Literal['nodejs22.x', 'nodejs24.x', 'python3.10', 'python3.11', 'python3.12', 'python3.13', 'python3.14', 'ruby3.3', 'ruby3.4', 'ruby4.0']
+
+CREATE_FUNCTION_BODY_RUNTIME_VALUES: set[CreateFunctionBodyRuntime] = { 'nodejs22.x', 'nodejs24.x', 'python3.10', 'python3.11', 'python3.12', 'python3.13', 'python3.14', 'ruby3.3', 'ruby3.4', 'ruby4.0', }
+
+def check_create_function_body_runtime(value: str) -> CreateFunctionBodyRuntime:
+ if value in CREATE_FUNCTION_BODY_RUNTIME_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_FUNCTION_BODY_RUNTIME_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_function_scheduler_request.py b/src/volcano_sdk/_generated/models/create_function_scheduler_request.py
new file mode 100644
index 00000000..2677f78f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_function_scheduler_request.py
@@ -0,0 +1,139 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.create_function_scheduler_request_payload import CreateFunctionSchedulerRequestPayload
+ from ..models.schedule_request import ScheduleRequest
+
+
+
+
+
+T = TypeVar("T", bound="CreateFunctionSchedulerRequest")
+
+
+
+@_attrs_define
+class CreateFunctionSchedulerRequest:
+ """
+ Attributes:
+ name (str):
+ schedule (ScheduleRequest):
+ enabled (bool | Unset): Default: True.
+ payload (CreateFunctionSchedulerRequestPayload | Unset):
+ regions (list[str] | Unset): Optional single explicit deployed region. If omitted, the scheduler chooses one
+ deployed region and invokes according to the cron expression.
+ """
+
+ name: str
+ schedule: ScheduleRequest
+ enabled: bool | Unset = True
+ payload: CreateFunctionSchedulerRequestPayload | Unset = UNSET
+ regions: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.create_function_scheduler_request_payload import CreateFunctionSchedulerRequestPayload
+ from ..models.schedule_request import ScheduleRequest
+ name = self.name
+
+ schedule = self.schedule.to_dict()
+
+ enabled = self.enabled
+
+ payload: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.payload, Unset):
+ payload = self.payload.to_dict()
+
+ regions: list[str] | Unset = UNSET
+ if not isinstance(self.regions, Unset):
+ regions = self.regions
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "schedule": schedule,
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if payload is not UNSET:
+ field_dict["payload"] = payload
+ if regions is not UNSET:
+ field_dict["regions"] = regions
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.create_function_scheduler_request_payload import CreateFunctionSchedulerRequestPayload
+ from ..models.schedule_request import ScheduleRequest
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ schedule = ScheduleRequest.from_dict(d.pop("schedule"))
+
+
+
+
+ enabled = d.pop("enabled", UNSET)
+
+ _payload = d.pop("payload", UNSET)
+ payload: CreateFunctionSchedulerRequestPayload | Unset
+ if isinstance(_payload, Unset):
+ payload = UNSET
+ else:
+ payload = CreateFunctionSchedulerRequestPayload.from_dict(_payload)
+
+
+
+
+ regions = cast(list[str], d.pop("regions", UNSET))
+
+
+ create_function_scheduler_request = cls(
+ name=name,
+ schedule=schedule,
+ enabled=enabled,
+ payload=payload,
+ regions=regions,
+ )
+
+
+ create_function_scheduler_request.additional_properties = d
+ return create_function_scheduler_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_function_scheduler_request_payload.py b/src/volcano_sdk/_generated/models/create_function_scheduler_request_payload.py
new file mode 100644
index 00000000..1fcf3b8c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_function_scheduler_request_payload.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateFunctionSchedulerRequestPayload")
+
+
+
+@_attrs_define
+class CreateFunctionSchedulerRequestPayload:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ create_function_scheduler_request_payload = cls(
+ )
+
+
+ create_function_scheduler_request_payload.additional_properties = d
+ return create_function_scheduler_request_payload
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_functions_batch_body.py b/src/volcano_sdk/_generated/models/create_functions_batch_body.py
new file mode 100644
index 00000000..e1e8d310
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_functions_batch_body.py
@@ -0,0 +1,125 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+import json
+from .. import types
+
+from ..types import UNSET, Unset
+
+from ..types import File, FileTypes
+from ..types import UNSET, Unset
+from io import BytesIO
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateFunctionsBatchBody")
+
+
+
+@_attrs_define
+class CreateFunctionsBatchBody:
+ """
+ Attributes:
+ functions (str): JSON array of functions with `name`, `runtime`, optional `handler`, and `file_field`. Each
+ `file_field` must name a multipart file field containing that function's ZIP or tar.gz source bundle.
+ code_0 (File | Unset): Function ZIP or tar.gz archive referenced by the first manifest entry's `file_field`;
+ additional code_N file fields may be included. Each archive is subject to SOURCE_ARCHIVE_SIZE_LIMIT_MB.
+ """
+
+ functions: str
+ code_0: File | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ functions = self.functions
+
+ code_0: FileTypes | Unset = UNSET
+ if not isinstance(self.code_0, Unset):
+ code_0 = self.code_0.to_tuple()
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "functions": functions,
+ })
+ if code_0 is not UNSET:
+ field_dict["code_0"] = code_0
+
+ return field_dict
+
+
+ def to_multipart(self) -> types.RequestFiles:
+ files: types.RequestFiles = []
+
+ files.append(("functions", (None, str(self.functions).encode(), "text/plain")))
+
+
+
+ if not isinstance(self.code_0, Unset):
+ files.append(("code_0", self.code_0.to_tuple()))
+
+
+
+
+ for prop_name, prop in self.additional_properties.items():
+ files.append((prop_name, (None, str(prop).encode(), "text/plain")))
+
+
+
+ return files
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ functions = d.pop("functions")
+
+ _code_0 = d.pop("code_0", UNSET)
+ code_0: File | Unset
+ if isinstance(_code_0, Unset):
+ code_0 = UNSET
+ else:
+ code_0 = File(
+ payload = BytesIO(_code_0)
+ )
+
+
+
+
+ create_functions_batch_body = cls(
+ functions=functions,
+ code_0=code_0,
+ )
+
+
+ create_functions_batch_body.additional_properties = d
+ return create_functions_batch_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_o_auth_config_request.py b/src/volcano_sdk/_generated/models/create_o_auth_config_request.py
new file mode 100644
index 00000000..82ea7ba3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_o_auth_config_request.py
@@ -0,0 +1,128 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.create_o_auth_config_request_provider import check_create_o_auth_config_request_provider
+from ..models.create_o_auth_config_request_provider import CreateOAuthConfigRequestProvider
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateOAuthConfigRequest")
+
+
+
+@_attrs_define
+class CreateOAuthConfigRequest:
+ """
+ Attributes:
+ provider (CreateOAuthConfigRequestProvider): Example: google.
+ client_id (str | Unset): Required for non-device providers. Must not be provided for `provider=device`; server
+ always auto-generates it. Example: 123456789.apps.googleusercontent.com.
+ client_secret (str | Unset): Required for non-device providers. Must not be provided for `provider=device`;
+ server always auto-generates it. Example: GOCSPX-abc123def456.
+ redirect_url (str | Unset): Required for non-device providers. Not used for `provider=device`. Example:
+ https://yourapp.com/auth/callback.
+ scopes (list[str] | Unset): Optional for non-device providers, uses provider defaults if omitted. Not used for
+ `provider=device`. Example: ['openid', 'email', 'profile'].
+ """
+
+ provider: CreateOAuthConfigRequestProvider
+ client_id: str | Unset = UNSET
+ client_secret: str | Unset = UNSET
+ redirect_url: str | Unset = UNSET
+ scopes: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ provider: str = self.provider
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ redirect_url = self.redirect_url
+
+ scopes: list[str] | Unset = UNSET
+ if not isinstance(self.scopes, Unset):
+ scopes = self.scopes
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "provider": provider,
+ })
+ if client_id is not UNSET:
+ field_dict["client_id"] = client_id
+ if client_secret is not UNSET:
+ field_dict["client_secret"] = client_secret
+ if redirect_url is not UNSET:
+ field_dict["redirect_url"] = redirect_url
+ if scopes is not UNSET:
+ field_dict["scopes"] = scopes
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ provider = check_create_o_auth_config_request_provider(d.pop("provider"))
+
+
+
+
+ client_id = d.pop("client_id", UNSET)
+
+ client_secret = d.pop("client_secret", UNSET)
+
+ redirect_url = d.pop("redirect_url", UNSET)
+
+ scopes = cast(list[str], d.pop("scopes", UNSET))
+
+
+ create_o_auth_config_request = cls(
+ provider=provider,
+ client_id=client_id,
+ client_secret=client_secret,
+ redirect_url=redirect_url,
+ scopes=scopes,
+ )
+
+
+ create_o_auth_config_request.additional_properties = d
+ return create_o_auth_config_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_o_auth_config_request_provider.py b/src/volcano_sdk/_generated/models/create_o_auth_config_request_provider.py
new file mode 100644
index 00000000..10c38258
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_o_auth_config_request_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateOAuthConfigRequestProvider = Literal['apple', 'device', 'github', 'google', 'microsoft']
+
+CREATE_O_AUTH_CONFIG_REQUEST_PROVIDER_VALUES: set[CreateOAuthConfigRequestProvider] = { 'apple', 'device', 'github', 'google', 'microsoft', }
+
+def check_create_o_auth_config_request_provider(value: str) -> CreateOAuthConfigRequestProvider:
+ if value in CREATE_O_AUTH_CONFIG_REQUEST_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_O_AUTH_CONFIG_REQUEST_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_project_request.py b/src/volcano_sdk/_generated/models/create_project_request.py
new file mode 100644
index 00000000..9b91e0bc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_project_request.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateProjectRequest")
+
+
+
+@_attrs_define
+class CreateProjectRequest:
+ """ Request to create a new project
+
+ Attributes:
+ name (str): Project name (must be unique).
+ Can only contain letters, numbers, underscores, and hyphens.
+ Example: my-awesome-app.
+ all_regions (bool | Unset): Optional region policy.
+ - `true` (default): project functions deploy to all configured regions
+ - `false`: project deploys only to `selected_regions`
+ Default: True.
+ selected_regions (list[str] | Unset): Optional region subset. Requires `all_regions=false`.
+ Region names must be a subset of platform `AWS_REGIONS`.
+ Example: ['us-east-1', 'us-west-2'].
+ """
+
+ name: str
+ all_regions: bool | Unset = True
+ selected_regions: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ all_regions = self.all_regions
+
+ selected_regions: list[str] | Unset = UNSET
+ if not isinstance(self.selected_regions, Unset):
+ selected_regions = self.selected_regions
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ })
+ if all_regions is not UNSET:
+ field_dict["all_regions"] = all_regions
+ if selected_regions is not UNSET:
+ field_dict["selected_regions"] = selected_regions
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ all_regions = d.pop("all_regions", UNSET)
+
+ selected_regions = cast(list[str], d.pop("selected_regions", UNSET))
+
+
+ create_project_request = cls(
+ name=name,
+ all_regions=all_regions,
+ selected_regions=selected_regions,
+ )
+
+
+ create_project_request.additional_properties = d
+ return create_project_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_service_key_body.py b/src/volcano_sdk/_generated/models/create_service_key_body.py
new file mode 100644
index 00000000..f4ce6430
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_service_key_body.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateServiceKeyBody")
+
+
+
+@_attrs_define
+class CreateServiceKeyBody:
+ """
+ Attributes:
+ name (str): Descriptive name for the key (e.g., "admin-dashboard", "background-jobs").
+ Can only contain letters, numbers, underscores, and hyphens.
+ Example: admin-dashboard.
+ permissions (list[str] | Unset): Optional least-privilege scope for the key. When omitted, empty, or
+ containing only blank strings, the key is granted full access (["*"])
+ for backward compatibility. Provide an explicit list (e.g.
+ ["functions.invoke", "locks.manage"]) to restrict the key; "*"
+ grants everything. Scope enforcement applies to function invocation,
+ storage object operations, and project locks.
+ Example: ['functions.invoke', 'locks.manage'].
+ """
+
+ name: str
+ permissions: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ permissions: list[str] | Unset = UNSET
+ if not isinstance(self.permissions, Unset):
+ permissions = self.permissions
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ })
+ if permissions is not UNSET:
+ field_dict["permissions"] = permissions
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ permissions = cast(list[str], d.pop("permissions", UNSET))
+
+
+ create_service_key_body = cls(
+ name=name,
+ permissions=permissions,
+ )
+
+
+ create_service_key_body.additional_properties = d
+ return create_service_key_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_storage_bucket_request.py b/src/volcano_sdk/_generated/models/create_storage_bucket_request.py
new file mode 100644
index 00000000..00b96028
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_storage_bucket_request.py
@@ -0,0 +1,101 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateStorageBucketRequest")
+
+
+
+@_attrs_define
+class CreateStorageBucketRequest:
+ """
+ Attributes:
+ name (str): Bucket name (alphanumeric, dashes, underscores)
+ file_size_limit (int | Unset): Maximum file size in bytes
+ allowed_mime_types (list[str] | Unset): Allowed MIME types (e.g., ["image/png", "image/jpeg"])
+ """
+
+ name: str
+ file_size_limit: int | Unset = UNSET
+ allowed_mime_types: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ file_size_limit = self.file_size_limit
+
+ allowed_mime_types: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_mime_types, Unset):
+ allowed_mime_types = self.allowed_mime_types
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ })
+ if file_size_limit is not UNSET:
+ field_dict["file_size_limit"] = file_size_limit
+ if allowed_mime_types is not UNSET:
+ field_dict["allowed_mime_types"] = allowed_mime_types
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ file_size_limit = d.pop("file_size_limit", UNSET)
+
+ allowed_mime_types = cast(list[str], d.pop("allowed_mime_types", UNSET))
+
+
+ create_storage_bucket_request = cls(
+ name=name,
+ file_size_limit=file_size_limit,
+ allowed_mime_types=allowed_mime_types,
+ )
+
+
+ create_storage_bucket_request.additional_properties = d
+ return create_storage_bucket_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_storage_policy_request.py b/src/volcano_sdk/_generated/models/create_storage_policy_request.py
new file mode 100644
index 00000000..42ba590a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_storage_policy_request.py
@@ -0,0 +1,98 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.create_storage_policy_request_operation import check_create_storage_policy_request_operation
+from ..models.create_storage_policy_request_operation import CreateStoragePolicyRequestOperation
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateStoragePolicyRequest")
+
+
+
+@_attrs_define
+class CreateStoragePolicyRequest:
+ """
+ Attributes:
+ name (str): Policy name
+ operation (CreateStoragePolicyRequestOperation): Operation this policy applies to
+ definition (str): Policy expression
+ """
+
+ name: str
+ operation: CreateStoragePolicyRequestOperation
+ definition: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ operation: str = self.operation
+
+ definition = self.definition
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "operation": operation,
+ "definition": definition,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ operation = check_create_storage_policy_request_operation(d.pop("operation"))
+
+
+
+
+ definition = d.pop("definition")
+
+ create_storage_policy_request = cls(
+ name=name,
+ operation=operation,
+ definition=definition,
+ )
+
+
+ create_storage_policy_request.additional_properties = d
+ return create_storage_policy_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_storage_policy_request_operation.py b/src/volcano_sdk/_generated/models/create_storage_policy_request_operation.py
new file mode 100644
index 00000000..8bfb1fda
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_storage_policy_request_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+CreateStoragePolicyRequestOperation = Literal['DELETE', 'INSERT', 'SELECT', 'UPDATE']
+
+CREATE_STORAGE_POLICY_REQUEST_OPERATION_VALUES: set[CreateStoragePolicyRequestOperation] = { 'DELETE', 'INSERT', 'SELECT', 'UPDATE', }
+
+def check_create_storage_policy_request_operation(value: str) -> CreateStoragePolicyRequestOperation:
+ if value in CREATE_STORAGE_POLICY_REQUEST_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {CREATE_STORAGE_POLICY_REQUEST_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/create_upload_session_request.py b/src/volcano_sdk/_generated/models/create_upload_session_request.py
new file mode 100644
index 00000000..078a2c23
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_upload_session_request.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateUploadSessionRequest")
+
+
+
+@_attrs_define
+class CreateUploadSessionRequest:
+ """ Request to create a resumable upload session
+
+ Attributes:
+ object_path (str): Target file path within the bucket Example: videos/large-file.mp4.
+ content_type (str): MIME type of the file Example: video/mp4.
+ total_size (int): Total file size in bytes (max 5TB) Example: 5368709120.
+ part_size (int | Unset): Part size in bytes (default: 25MB, min: 5MB, max: 25MB) Example: 26214400.
+ """
+
+ object_path: str
+ content_type: str
+ total_size: int
+ part_size: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ object_path = self.object_path
+
+ content_type = self.content_type
+
+ total_size = self.total_size
+
+ part_size = self.part_size
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "object_path": object_path,
+ "content_type": content_type,
+ "total_size": total_size,
+ })
+ if part_size is not UNSET:
+ field_dict["part_size"] = part_size
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ object_path = d.pop("object_path")
+
+ content_type = d.pop("content_type")
+
+ total_size = d.pop("total_size")
+
+ part_size = d.pop("part_size", UNSET)
+
+ create_upload_session_request = cls(
+ object_path=object_path,
+ content_type=content_type,
+ total_size=total_size,
+ part_size=part_size,
+ )
+
+
+ create_upload_session_request.additional_properties = d
+ return create_upload_session_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_upload_session_response.py b/src/volcano_sdk/_generated/models/create_upload_session_response.py
new file mode 100644
index 00000000..bbc08963
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_upload_session_response.py
@@ -0,0 +1,119 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateUploadSessionResponse")
+
+
+
+@_attrs_define
+class CreateUploadSessionResponse:
+ """ Response when creating an upload session
+
+ Attributes:
+ session_id (str | Unset): Upload session ID Example: session-abc123.
+ part_size (int | Unset): Actual part size to use Example: 26214400.
+ total_parts (int | Unset): Number of parts to upload Example: 52.
+ expires_at (datetime.datetime | Unset): When the session expires (7 days from creation) Example:
+ 2024-01-22T10:30:00Z.
+ """
+
+ session_id: str | Unset = UNSET
+ part_size: int | Unset = UNSET
+ total_parts: int | Unset = UNSET
+ expires_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ session_id = self.session_id
+
+ part_size = self.part_size
+
+ total_parts = self.total_parts
+
+ expires_at: str | Unset = UNSET
+ if not isinstance(self.expires_at, Unset):
+ expires_at = self.expires_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if session_id is not UNSET:
+ field_dict["session_id"] = session_id
+ if part_size is not UNSET:
+ field_dict["part_size"] = part_size
+ if total_parts is not UNSET:
+ field_dict["total_parts"] = total_parts
+ if expires_at is not UNSET:
+ field_dict["expires_at"] = expires_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ session_id = d.pop("session_id", UNSET)
+
+ part_size = d.pop("part_size", UNSET)
+
+ total_parts = d.pop("total_parts", UNSET)
+
+ _expires_at = d.pop("expires_at", UNSET)
+ expires_at: datetime.datetime | Unset
+ if isinstance(_expires_at, Unset):
+ expires_at = UNSET
+ else:
+ expires_at = datetime.datetime.fromisoformat(_expires_at)
+
+
+
+
+ create_upload_session_response = cls(
+ session_id=session_id,
+ part_size=part_size,
+ total_parts=total_parts,
+ expires_at=expires_at,
+ )
+
+
+ create_upload_session_response.additional_properties = d
+ return create_upload_session_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/create_variable_request.py b/src/volcano_sdk/_generated/models/create_variable_request.py
new file mode 100644
index 00000000..183236b3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/create_variable_request.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="CreateVariableRequest")
+
+
+
+@_attrs_define
+class CreateVariableRequest:
+ """
+ Attributes:
+ name (str):
+ value (str):
+ """
+
+ name: str
+ value: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ value = d.pop("value")
+
+ create_variable_request = cls(
+ name=name,
+ value=value,
+ )
+
+
+ create_variable_request.additional_properties = d
+ return create_variable_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database.py b/src/volcano_sdk/_generated/models/database.py
new file mode 100644
index 00000000..e1d87278
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database.py
@@ -0,0 +1,247 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.database_database_type import check_database_database_type
+from ..models.database_database_type import DatabaseDatabaseType
+from ..models.database_status import check_database_status
+from ..models.database_status import DatabaseStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="Database")
+
+
+
+@_attrs_define
+class Database:
+ """ PostgreSQL database with automatic scalability and security features.
+
+ Attributes:
+ id (UUID):
+ project_id (UUID):
+ name (str): Database name
+ status (DatabaseStatus): Database provisioning status
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ provisioning_started_at (datetime.datetime | Unset): Timestamp when the current provisioning phase started
+ connection_string (str | Unset): Secure PostgreSQL connection URI for your database.
+
+ The database is identified by the globally-unique username
+ (`volcano_client_{database_id}`) already in this URI; the
+ `application_name` parameter only selects the access mode:
+ - `volcano_full_access` — Full admin access (DDL, migrations)
+ - `volcano_user_access:{user_id}` — User impersonation (RLS enforced)
+ - `volcano_user_access` — Anonymous access (anon role, RLS enforced)
+ region (str | Unset): Region where the database is hosted Example: aws-us-east-1.
+ pg_version (str | Unset): PostgreSQL major version Example: 16.
+ database_type (DatabaseDatabaseType | Unset): Database size tier that determines available RAM and scaling
+ limits.
+ Example: volcano-db-xs.
+ storage_bytes (int | Unset): Latest observed on-disk size from `pg_database_size`, in bytes. This
+ point-in-time gauge may be absent until the database has been sampled.
+ Summing the latest samples for every database in a project produces
+ the project's "Database Storage (Bytes)" usage gauge. Populated on
+ database list responses; single-database responses omit it.
+ last_invoked_at (datetime.datetime | Unset): Most recent request timestamp for this database
+ """
+
+ id: UUID
+ project_id: UUID
+ name: str
+ status: DatabaseStatus
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ provisioning_started_at: datetime.datetime | Unset = UNSET
+ connection_string: str | Unset = UNSET
+ region: str | Unset = UNSET
+ pg_version: str | Unset = UNSET
+ database_type: DatabaseDatabaseType | Unset = UNSET
+ storage_bytes: int | Unset = UNSET
+ last_invoked_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ project_id = str(self.project_id)
+
+ name = self.name
+
+ status: str = self.status
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ provisioning_started_at: str | Unset = UNSET
+ if not isinstance(self.provisioning_started_at, Unset):
+ provisioning_started_at = self.provisioning_started_at.isoformat()
+
+ connection_string = self.connection_string
+
+ region = self.region
+
+ pg_version = self.pg_version
+
+ database_type: str | Unset = UNSET
+ if not isinstance(self.database_type, Unset):
+ database_type = self.database_type
+
+
+ storage_bytes = self.storage_bytes
+
+ last_invoked_at: str | Unset = UNSET
+ if not isinstance(self.last_invoked_at, Unset):
+ last_invoked_at = self.last_invoked_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "project_id": project_id,
+ "name": name,
+ "status": status,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if provisioning_started_at is not UNSET:
+ field_dict["provisioning_started_at"] = provisioning_started_at
+ if connection_string is not UNSET:
+ field_dict["connection_string"] = connection_string
+ if region is not UNSET:
+ field_dict["region"] = region
+ if pg_version is not UNSET:
+ field_dict["pg_version"] = pg_version
+ if database_type is not UNSET:
+ field_dict["database_type"] = database_type
+ if storage_bytes is not UNSET:
+ field_dict["storage_bytes"] = storage_bytes
+ if last_invoked_at is not UNSET:
+ field_dict["last_invoked_at"] = last_invoked_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ name = d.pop("name")
+
+ status = check_database_status(d.pop("status"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ _provisioning_started_at = d.pop("provisioning_started_at", UNSET)
+ provisioning_started_at: datetime.datetime | Unset
+ if isinstance(_provisioning_started_at, Unset):
+ provisioning_started_at = UNSET
+ else:
+ provisioning_started_at = datetime.datetime.fromisoformat(_provisioning_started_at)
+
+
+
+
+ connection_string = d.pop("connection_string", UNSET)
+
+ region = d.pop("region", UNSET)
+
+ pg_version = d.pop("pg_version", UNSET)
+
+ _database_type = d.pop("database_type", UNSET)
+ database_type: DatabaseDatabaseType | Unset
+ if isinstance(_database_type, Unset):
+ database_type = UNSET
+ else:
+ database_type = check_database_database_type(_database_type)
+
+
+
+
+ storage_bytes = d.pop("storage_bytes", UNSET)
+
+ _last_invoked_at = d.pop("last_invoked_at", UNSET)
+ last_invoked_at: datetime.datetime | Unset
+ if isinstance(_last_invoked_at, Unset):
+ last_invoked_at = UNSET
+ else:
+ last_invoked_at = datetime.datetime.fromisoformat(_last_invoked_at)
+
+
+
+
+ database = cls(
+ id=id,
+ project_id=project_id,
+ name=name,
+ status=status,
+ created_at=created_at,
+ updated_at=updated_at,
+ provisioning_started_at=provisioning_started_at,
+ connection_string=connection_string,
+ region=region,
+ pg_version=pg_version,
+ database_type=database_type,
+ storage_bytes=storage_bytes,
+ last_invoked_at=last_invoked_at,
+ )
+
+
+ database.additional_properties = d
+ return database
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_branch.py b/src/volcano_sdk/_generated/models/database_branch.py
new file mode 100644
index 00000000..021d724a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_branch.py
@@ -0,0 +1,235 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.database_branch_status import check_database_branch_status
+from ..models.database_branch_status import DatabaseBranchStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseBranch")
+
+
+
+@_attrs_define
+class DatabaseBranch:
+ """ A copy-on-write fork of a database, for development and testing.
+
+ A branch starts as an exact copy of its parent's data and diverges from
+ there. It has its own connection string and its own credential, so a
+ branch password cannot reach the parent.
+
+ Every branch expires. `expires_at` is a hard deadline: once it passes the
+ branch stops accepting connections and is deleted. Use `PATCH` to extend
+ a branch you are still working on.
+
+ Attributes:
+ id (UUID):
+ database_id (UUID): The parent database this branch was forked from.
+ project_id (UUID):
+ name (str): Branch name, unique within the parent database.
+ status (DatabaseBranchStatus): Branch status. A new branch starts `provisioning` and is not
+ connectable until it reports `active`; poll this endpoint until it
+ does. `connection_string` is only present while `active`.
+
+ `provisioning` also covers a branch being rebuilt after a `reset`,
+ and a build that is between retries, so it is the status to keep
+ waiting on. `failed` is terminal: it means the platform gave up, and
+ the branch will not become `active` on its own.
+ ttl_seconds (int): The lifetime the branch was created with. Resetting a branch re-arms
+ this same duration, so a reset never shortens a branch's remaining
+ life.
+ expires_at (datetime.datetime): When the branch stops serving connections and becomes eligible for
+ deletion. Enforced on the connection path, so it holds even if
+ reclamation is delayed.
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ connection_string (str | Unset): PostgreSQL connection URI for this branch. Present only while the
+ branch is `active`.
+
+ The URI carries the branch's own globally-unique username and
+ password; `application_name` selects the access mode exactly as it
+ does for the parent database:
+ - `volcano_full_access` — Full admin access (DDL, migrations)
+ - `volcano_user_access:{user_id}` — User impersonation (RLS enforced)
+ - `volcano_user_access` — Anonymous access (anon role, RLS enforced)
+ storage_bytes (int | Unset): Bytes this branch has diverged from its parent, which is what a
+ branch actually costs. Shared pages are not counted twice. Counts
+ against the parent database's storage allowance. Absent until the
+ branch has been sampled.
+ last_invoked_at (datetime.datetime | Unset): Most recent request timestamp for this branch
+ """
+
+ id: UUID
+ database_id: UUID
+ project_id: UUID
+ name: str
+ status: DatabaseBranchStatus
+ ttl_seconds: int
+ expires_at: datetime.datetime
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ connection_string: str | Unset = UNSET
+ storage_bytes: int | Unset = UNSET
+ last_invoked_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ database_id = str(self.database_id)
+
+ project_id = str(self.project_id)
+
+ name = self.name
+
+ status: str = self.status
+
+ ttl_seconds = self.ttl_seconds
+
+ expires_at = self.expires_at.isoformat()
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ connection_string = self.connection_string
+
+ storage_bytes = self.storage_bytes
+
+ last_invoked_at: str | Unset = UNSET
+ if not isinstance(self.last_invoked_at, Unset):
+ last_invoked_at = self.last_invoked_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "database_id": database_id,
+ "project_id": project_id,
+ "name": name,
+ "status": status,
+ "ttl_seconds": ttl_seconds,
+ "expires_at": expires_at,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if connection_string is not UNSET:
+ field_dict["connection_string"] = connection_string
+ if storage_bytes is not UNSET:
+ field_dict["storage_bytes"] = storage_bytes
+ if last_invoked_at is not UNSET:
+ field_dict["last_invoked_at"] = last_invoked_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ database_id = UUID(d.pop("database_id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ name = d.pop("name")
+
+ status = check_database_branch_status(d.pop("status"))
+
+
+
+
+ ttl_seconds = d.pop("ttl_seconds")
+
+ expires_at = datetime.datetime.fromisoformat(d.pop("expires_at"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ connection_string = d.pop("connection_string", UNSET)
+
+ storage_bytes = d.pop("storage_bytes", UNSET)
+
+ _last_invoked_at = d.pop("last_invoked_at", UNSET)
+ last_invoked_at: datetime.datetime | Unset
+ if isinstance(_last_invoked_at, Unset):
+ last_invoked_at = UNSET
+ else:
+ last_invoked_at = datetime.datetime.fromisoformat(_last_invoked_at)
+
+
+
+
+ database_branch = cls(
+ id=id,
+ database_id=database_id,
+ project_id=project_id,
+ name=name,
+ status=status,
+ ttl_seconds=ttl_seconds,
+ expires_at=expires_at,
+ created_at=created_at,
+ updated_at=updated_at,
+ connection_string=connection_string,
+ storage_bytes=storage_bytes,
+ last_invoked_at=last_invoked_at,
+ )
+
+
+ database_branch.additional_properties = d
+ return database_branch
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_branch_list.py b/src/volcano_sdk/_generated/models/database_branch_list.py
new file mode 100644
index 00000000..f737c51d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_branch_list.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_branch import DatabaseBranch
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseBranchList")
+
+
+
+@_attrs_define
+class DatabaseBranchList:
+ """
+ Attributes:
+ data (list[DatabaseBranch]):
+ """
+
+ data: list[DatabaseBranch]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_branch import DatabaseBranch
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_branch import DatabaseBranch
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = DatabaseBranch.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ database_branch_list = cls(
+ data=data,
+ )
+
+
+ database_branch_list.additional_properties = d
+ return database_branch_list
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_branch_status.py b/src/volcano_sdk/_generated/models/database_branch_status.py
new file mode 100644
index 00000000..44c8a027
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_branch_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DatabaseBranchStatus = Literal['active', 'deleting', 'failed', 'provisioning']
+
+DATABASE_BRANCH_STATUS_VALUES: set[DatabaseBranchStatus] = { 'active', 'deleting', 'failed', 'provisioning', }
+
+def check_database_branch_status(value: str) -> DatabaseBranchStatus:
+ if value in DATABASE_BRANCH_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DATABASE_BRANCH_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/database_branch_storage.py b/src/volcano_sdk/_generated/models/database_branch_storage.py
new file mode 100644
index 00000000..d831e45c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_branch_storage.py
@@ -0,0 +1,99 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseBranchStorage")
+
+
+
+@_attrs_define
+class DatabaseBranchStorage:
+ """ One branch's contribution to its parent database's storage.
+
+ Attributes:
+ id (UUID):
+ name (str): Branch name
+ storage_bytes (int): Bytes this branch has diverged from its parent. Pages the branch
+ still shares with the parent are not counted, so this is what the
+ branch actually adds to the total rather than its apparent size.
+ """
+
+ id: UUID
+ name: str
+ storage_bytes: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ name = self.name
+
+ storage_bytes = self.storage_bytes
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ "storage_bytes": storage_bytes,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ storage_bytes = d.pop("storage_bytes")
+
+ database_branch_storage = cls(
+ id=id,
+ name=name,
+ storage_bytes=storage_bytes,
+ )
+
+
+ database_branch_storage.additional_properties = d
+ return database_branch_storage
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_database_type.py b/src/volcano_sdk/_generated/models/database_database_type.py
new file mode 100644
index 00000000..2b613ac0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_database_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DatabaseDatabaseType = Literal['volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs']
+
+DATABASE_DATABASE_TYPE_VALUES: set[DatabaseDatabaseType] = { 'volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs', }
+
+def check_database_database_type(value: str) -> DatabaseDatabaseType:
+ if value in DATABASE_DATABASE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DATABASE_DATABASE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/database_delete_request.py b/src/volcano_sdk/_generated/models/database_delete_request.py
new file mode 100644
index 00000000..59446d19
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_delete_request.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_query_filter import DatabaseQueryFilter
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseDeleteRequest")
+
+
+
+@_attrs_define
+class DatabaseDeleteRequest:
+ """
+ Attributes:
+ table (str): Table name Example: posts.
+ filters (list[DatabaseQueryFilter]): WHERE conditions (required for safety) Example: [{'column': 'id',
+ 'operator': 'eq', 'value': 'post-uuid'}].
+ """
+
+ table: str
+ filters: list[DatabaseQueryFilter]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ table = self.table
+
+ filters = []
+ for filters_item_data in self.filters:
+ filters_item = filters_item_data.to_dict()
+ filters.append(filters_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "table": table,
+ "filters": filters,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ d = dict(src_dict)
+ table = d.pop("table")
+
+ filters = []
+ _filters = d.pop("filters")
+ for filters_item_data in (_filters):
+ filters_item = DatabaseQueryFilter.from_dict(filters_item_data)
+
+
+
+ filters.append(filters_item)
+
+
+ database_delete_request = cls(
+ table=table,
+ filters=filters,
+ )
+
+
+ database_delete_request.additional_properties = d
+ return database_delete_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_insert_request.py b/src/volcano_sdk/_generated/models/database_insert_request.py
new file mode 100644
index 00000000..6f37b44e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_insert_request.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_insert_request_values import DatabaseInsertRequestValues
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseInsertRequest")
+
+
+
+@_attrs_define
+class DatabaseInsertRequest:
+ """
+ Attributes:
+ table (str): Table name Example: posts.
+ values (DatabaseInsertRequestValues): Column values to insert Example: {'title': 'My New Post', 'content': 'This
+ is the content', 'status': 'draft'}.
+ """
+
+ table: str
+ values: DatabaseInsertRequestValues
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_insert_request_values import DatabaseInsertRequestValues
+ table = self.table
+
+ values = self.values.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "table": table,
+ "values": values,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_insert_request_values import DatabaseInsertRequestValues
+ d = dict(src_dict)
+ table = d.pop("table")
+
+ values = DatabaseInsertRequestValues.from_dict(d.pop("values"))
+
+
+
+
+ database_insert_request = cls(
+ table=table,
+ values=values,
+ )
+
+
+ database_insert_request.additional_properties = d
+ return database_insert_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_insert_request_values.py b/src/volcano_sdk/_generated/models/database_insert_request_values.py
new file mode 100644
index 00000000..2c169965
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_insert_request_values.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseInsertRequestValues")
+
+
+
+@_attrs_define
+class DatabaseInsertRequestValues:
+ """ Column values to insert
+
+ Example:
+ {'title': 'My New Post', 'content': 'This is the content', 'status': 'draft'}
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ database_insert_request_values = cls(
+ )
+
+
+ database_insert_request_values.additional_properties = d
+ return database_insert_request_values
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_query_filter.py b/src/volcano_sdk/_generated/models/database_query_filter.py
new file mode 100644
index 00000000..63b1c9ff
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_filter.py
@@ -0,0 +1,142 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.database_query_filter_operator import check_database_query_filter_operator
+from ..models.database_query_filter_operator import DatabaseQueryFilterOperator
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseQueryFilter")
+
+
+
+@_attrs_define
+class DatabaseQueryFilter:
+ """ One WHERE condition. Conditions are combined with AND.
+
+ Attributes:
+ column (str): Example: status.
+ operator (DatabaseQueryFilterOperator): Filter operators:
+ - eq: equals (=)
+ - neq: not equals (<>)
+ - gt: greater than (>)
+ - gte: greater than or equal (>=)
+ - lt: less than (<)
+ - lte: less than or equal (<=)
+ - like: pattern match (LIKE)
+ - ilike: case-insensitive pattern match (ILIKE)
+ - is: IS NULL / IS NOT NULL
+ - in: IN array
+ Example: eq.
+ value (bool | float | list[bool | float | str] | None | str): Example: published.
+ """
+
+ column: str
+ operator: DatabaseQueryFilterOperator
+ value: bool | float | list[bool | float | str] | None | str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ column = self.column
+
+ operator: str = self.operator
+
+ value: bool | float | list[bool | float | str] | None | str
+ if isinstance(self.value, list):
+ value = []
+ for value_type_3_item_data in self.value:
+ value_type_3_item: bool | float | str
+ value_type_3_item = value_type_3_item_data
+ value.append(value_type_3_item)
+
+
+ else:
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "column": column,
+ "operator": operator,
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ column = d.pop("column")
+
+ operator = check_database_query_filter_operator(d.pop("operator"))
+
+
+
+
+ def _parse_value(data: object) -> bool | float | list[bool | float | str] | None | str:
+ if data is None:
+ return data
+ try:
+ if not isinstance(data, list):
+ raise TypeError()
+ value_type_3 = []
+ _value_type_3 = data
+ for value_type_3_item_data in (_value_type_3):
+ def _parse_value_type_3_item(data: object) -> bool | float | str:
+ return cast(bool | float | str, data)
+
+ value_type_3_item = _parse_value_type_3_item(value_type_3_item_data)
+
+ value_type_3.append(value_type_3_item)
+
+ return value_type_3
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(bool | float | list[bool | float | str] | None | str, data)
+
+ value = _parse_value(d.pop("value"))
+
+
+ database_query_filter = cls(
+ column=column,
+ operator=operator,
+ value=value,
+ )
+
+
+ database_query_filter.additional_properties = d
+ return database_query_filter
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_query_filter_operator.py b/src/volcano_sdk/_generated/models/database_query_filter_operator.py
new file mode 100644
index 00000000..b52084a7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_filter_operator.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DatabaseQueryFilterOperator = Literal['eq', 'gt', 'gte', 'ilike', 'in', 'is', 'like', 'lt', 'lte', 'neq']
+
+DATABASE_QUERY_FILTER_OPERATOR_VALUES: set[DatabaseQueryFilterOperator] = { 'eq', 'gt', 'gte', 'ilike', 'in', 'is', 'like', 'lt', 'lte', 'neq', }
+
+def check_database_query_filter_operator(value: str) -> DatabaseQueryFilterOperator:
+ if value in DATABASE_QUERY_FILTER_OPERATOR_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DATABASE_QUERY_FILTER_OPERATOR_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/database_query_order.py b/src/volcano_sdk/_generated/models/database_query_order.py
new file mode 100644
index 00000000..5ca48b13
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_order.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseQueryOrder")
+
+
+
+@_attrs_define
+class DatabaseQueryOrder:
+ """ One ORDER BY clause.
+
+ Attributes:
+ column (str): Example: created_at.
+ ascending (bool | Unset): Default: True.
+ nulls_first (bool | Unset): Default: False.
+ """
+
+ column: str
+ ascending: bool | Unset = True
+ nulls_first: bool | Unset = False
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ column = self.column
+
+ ascending = self.ascending
+
+ nulls_first = self.nulls_first
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "column": column,
+ })
+ if ascending is not UNSET:
+ field_dict["ascending"] = ascending
+ if nulls_first is not UNSET:
+ field_dict["nulls_first"] = nulls_first
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ column = d.pop("column")
+
+ ascending = d.pop("ascending", UNSET)
+
+ nulls_first = d.pop("nulls_first", UNSET)
+
+ database_query_order = cls(
+ column=column,
+ ascending=ascending,
+ nulls_first=nulls_first,
+ )
+
+
+ database_query_order.additional_properties = d
+ return database_query_order
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_query_performance_database.py b/src/volcano_sdk/_generated/models/database_query_performance_database.py
new file mode 100644
index 00000000..ed0bfa9c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_performance_database.py
@@ -0,0 +1,88 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseQueryPerformanceDatabase")
+
+
+
+@_attrs_define
+class DatabaseQueryPerformanceDatabase:
+ """
+ Attributes:
+ id (UUID):
+ name (str):
+ """
+
+ id: UUID
+ name: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ database_query_performance_database = cls(
+ id=id,
+ name=name,
+ )
+
+
+ database_query_performance_database.additional_properties = d
+ return database_query_performance_database
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_query_performance_item.py b/src/volcano_sdk/_generated/models/database_query_performance_item.py
new file mode 100644
index 00000000..8dc98ad2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_performance_item.py
@@ -0,0 +1,156 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_query_performance_database import DatabaseQueryPerformanceDatabase
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseQueryPerformanceItem")
+
+
+
+@_attrs_define
+class DatabaseQueryPerformanceItem:
+ """
+ Attributes:
+ query_id (str): pg_stat_statements query identifier.
+ query (str): Normalized and obfuscated representative query text.
+ database (DatabaseQueryPerformanceDatabase):
+ role (str): Database role used for the query.
+ calls (int):
+ total_exec_time_seconds (float): Cumulative total execution time from pg_stat_statements in seconds.
+ max_exec_time_seconds (float):
+ mean_exec_time_seconds (float):
+ min_exec_time_seconds (float):
+ rows_processed (int):
+ """
+
+ query_id: str
+ query: str
+ database: DatabaseQueryPerformanceDatabase
+ role: str
+ calls: int
+ total_exec_time_seconds: float
+ max_exec_time_seconds: float
+ mean_exec_time_seconds: float
+ min_exec_time_seconds: float
+ rows_processed: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_query_performance_database import DatabaseQueryPerformanceDatabase
+ query_id = self.query_id
+
+ query = self.query
+
+ database = self.database.to_dict()
+
+ role = self.role
+
+ calls = self.calls
+
+ total_exec_time_seconds = self.total_exec_time_seconds
+
+ max_exec_time_seconds = self.max_exec_time_seconds
+
+ mean_exec_time_seconds = self.mean_exec_time_seconds
+
+ min_exec_time_seconds = self.min_exec_time_seconds
+
+ rows_processed = self.rows_processed
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "query_id": query_id,
+ "query": query,
+ "database": database,
+ "role": role,
+ "calls": calls,
+ "total_exec_time_seconds": total_exec_time_seconds,
+ "max_exec_time_seconds": max_exec_time_seconds,
+ "mean_exec_time_seconds": mean_exec_time_seconds,
+ "min_exec_time_seconds": min_exec_time_seconds,
+ "rows_processed": rows_processed,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_query_performance_database import DatabaseQueryPerformanceDatabase
+ d = dict(src_dict)
+ query_id = d.pop("query_id")
+
+ query = d.pop("query")
+
+ database = DatabaseQueryPerformanceDatabase.from_dict(d.pop("database"))
+
+
+
+
+ role = d.pop("role")
+
+ calls = d.pop("calls")
+
+ total_exec_time_seconds = d.pop("total_exec_time_seconds")
+
+ max_exec_time_seconds = d.pop("max_exec_time_seconds")
+
+ mean_exec_time_seconds = d.pop("mean_exec_time_seconds")
+
+ min_exec_time_seconds = d.pop("min_exec_time_seconds")
+
+ rows_processed = d.pop("rows_processed")
+
+ database_query_performance_item = cls(
+ query_id=query_id,
+ query=query,
+ database=database,
+ role=role,
+ calls=calls,
+ total_exec_time_seconds=total_exec_time_seconds,
+ max_exec_time_seconds=max_exec_time_seconds,
+ mean_exec_time_seconds=mean_exec_time_seconds,
+ min_exec_time_seconds=min_exec_time_seconds,
+ rows_processed=rows_processed,
+ )
+
+
+ database_query_performance_item.additional_properties = d
+ return database_query_performance_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_query_performance_response.py b/src/volcano_sdk/_generated/models/database_query_performance_response.py
new file mode 100644
index 00000000..d66598c2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_performance_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_query_performance_item import DatabaseQueryPerformanceItem
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseQueryPerformanceResponse")
+
+
+
+@_attrs_define
+class DatabaseQueryPerformanceResponse:
+ """
+ Attributes:
+ data (list[DatabaseQueryPerformanceItem]):
+ """
+
+ data: list[DatabaseQueryPerformanceItem]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_query_performance_item import DatabaseQueryPerformanceItem
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_query_performance_item import DatabaseQueryPerformanceItem
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = DatabaseQueryPerformanceItem.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ database_query_performance_response = cls(
+ data=data,
+ )
+
+
+ database_query_performance_response.additional_properties = d
+ return database_query_performance_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_query_result.py b/src/volcano_sdk/_generated/models/database_query_result.py
new file mode 100644
index 00000000..6b5aca34
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_result.py
@@ -0,0 +1,111 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_query_result_data_item import DatabaseQueryResultDataItem
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseQueryResult")
+
+
+
+@_attrs_define
+class DatabaseQueryResult:
+ """ Rows returned by a data API request. RLS-filtered unless the request was
+ made with a service key.
+
+ Attributes:
+ data (list[DatabaseQueryResultDataItem] | Unset): Result rows
+ count (int | Unset): Number of rows returned
+ """
+
+ data: list[DatabaseQueryResultDataItem] | Unset = UNSET
+ count: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_query_result_data_item import DatabaseQueryResultDataItem
+ data: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.data, Unset):
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ count = self.count
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if data is not UNSET:
+ field_dict["data"] = data
+ if count is not UNSET:
+ field_dict["count"] = count
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_query_result_data_item import DatabaseQueryResultDataItem
+ d = dict(src_dict)
+ _data = d.pop("data", UNSET)
+ data: list[DatabaseQueryResultDataItem] | Unset = UNSET
+ if _data is not UNSET:
+ data = []
+ for data_item_data in _data:
+ data_item = DatabaseQueryResultDataItem.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ count = d.pop("count", UNSET)
+
+ database_query_result = cls(
+ data=data,
+ count=count,
+ )
+
+
+ database_query_result.additional_properties = d
+ return database_query_result
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_query_result_data_item.py b/src/volcano_sdk/_generated/models/database_query_result_data_item.py
new file mode 100644
index 00000000..79238345
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_query_result_data_item.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseQueryResultDataItem")
+
+
+
+@_attrs_define
+class DatabaseQueryResultDataItem:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ database_query_result_data_item = cls(
+ )
+
+
+ database_query_result_data_item.additional_properties = d
+ return database_query_result_data_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_select_request.py b/src/volcano_sdk/_generated/models/database_select_request.py
new file mode 100644
index 00000000..0b45a8e9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_select_request.py
@@ -0,0 +1,171 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ from ..models.database_query_order import DatabaseQueryOrder
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseSelectRequest")
+
+
+
+@_attrs_define
+class DatabaseSelectRequest:
+ """
+ Attributes:
+ table (str): Table name to query Example: posts.
+ select (list[str] | Unset): Columns to select (omit for *) Example: ['id', 'title', 'content', 'created_at'].
+ filters (list[DatabaseQueryFilter] | Unset): WHERE conditions (combined with AND) Example: [{'column': 'status',
+ 'operator': 'eq', 'value': 'published'}, {'column': 'views', 'operator': 'gt', 'value': 100}].
+ order (list[DatabaseQueryOrder] | Unset): ORDER BY clauses Example: [{'column': 'created_at', 'ascending':
+ False}].
+ limit (int | Unset): Maximum rows to return Example: 10.
+ offset (int | Unset): Number of rows to skip (for pagination)
+ """
+
+ table: str
+ select: list[str] | Unset = UNSET
+ filters: list[DatabaseQueryFilter] | Unset = UNSET
+ order: list[DatabaseQueryOrder] | Unset = UNSET
+ limit: int | Unset = UNSET
+ offset: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ from ..models.database_query_order import DatabaseQueryOrder
+ table = self.table
+
+ select: list[str] | Unset = UNSET
+ if not isinstance(self.select, Unset):
+ select = self.select
+
+
+
+ filters: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.filters, Unset):
+ filters = []
+ for filters_item_data in self.filters:
+ filters_item = filters_item_data.to_dict()
+ filters.append(filters_item)
+
+
+
+ order: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.order, Unset):
+ order = []
+ for order_item_data in self.order:
+ order_item = order_item_data.to_dict()
+ order.append(order_item)
+
+
+
+ limit = self.limit
+
+ offset = self.offset
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "table": table,
+ })
+ if select is not UNSET:
+ field_dict["select"] = select
+ if filters is not UNSET:
+ field_dict["filters"] = filters
+ if order is not UNSET:
+ field_dict["order"] = order
+ if limit is not UNSET:
+ field_dict["limit"] = limit
+ if offset is not UNSET:
+ field_dict["offset"] = offset
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ from ..models.database_query_order import DatabaseQueryOrder
+ d = dict(src_dict)
+ table = d.pop("table")
+
+ select = cast(list[str], d.pop("select", UNSET))
+
+
+ _filters = d.pop("filters", UNSET)
+ filters: list[DatabaseQueryFilter] | Unset = UNSET
+ if _filters is not UNSET:
+ filters = []
+ for filters_item_data in _filters:
+ filters_item = DatabaseQueryFilter.from_dict(filters_item_data)
+
+
+
+ filters.append(filters_item)
+
+
+ _order = d.pop("order", UNSET)
+ order: list[DatabaseQueryOrder] | Unset = UNSET
+ if _order is not UNSET:
+ order = []
+ for order_item_data in _order:
+ order_item = DatabaseQueryOrder.from_dict(order_item_data)
+
+
+
+ order.append(order_item)
+
+
+ limit = d.pop("limit", UNSET)
+
+ offset = d.pop("offset", UNSET)
+
+ database_select_request = cls(
+ table=table,
+ select=select,
+ filters=filters,
+ order=order,
+ limit=limit,
+ offset=offset,
+ )
+
+
+ database_select_request.additional_properties = d
+ return database_select_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_stats.py b/src/volcano_sdk/_generated/models/database_stats.py
new file mode 100644
index 00000000..35784356
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_stats.py
@@ -0,0 +1,192 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.database_stats_granularity import check_database_stats_granularity
+from ..models.database_stats_granularity import DatabaseStatsGranularity
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_branch_storage import DatabaseBranchStorage
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseStats")
+
+
+
+@_attrs_define
+class DatabaseStats:
+ """
+ Attributes:
+ current_storage_bytes (int): On-disk size right now, in bytes: the database itself plus every
+ branch's divergence from it. This is the figure the storage
+ allowance is enforced against. `branches` breaks it down.
+ current_storage_mb (float): `current_storage_bytes` expressed in megabytes.
+ storage_bytes (int): Total storage used in bytes (data + WAL)
+ data_written_bytes (int): Total data written in bytes
+ data_transfer_bytes (int): Total data transferred in bytes
+ compute_time_seconds (float): Total CPU seconds consumed
+ active_time_seconds (float): Total active compute time in seconds
+ branches (list[DatabaseBranchStorage] | Unset): Per-branch contribution to `current_storage_bytes`. Empty when
+ the
+ database has no branches. A branch that has not diverged from its
+ parent contributes nothing.
+ time_range (str | Unset): Time range of the metrics (e.g., "2024-01-01T00:00:00Z to 2024-01-02T00:00:00Z")
+ granularity (DatabaseStatsGranularity | Unset): Granularity of the aggregated metrics
+ """
+
+ current_storage_bytes: int
+ current_storage_mb: float
+ storage_bytes: int
+ data_written_bytes: int
+ data_transfer_bytes: int
+ compute_time_seconds: float
+ active_time_seconds: float
+ branches: list[DatabaseBranchStorage] | Unset = UNSET
+ time_range: str | Unset = UNSET
+ granularity: DatabaseStatsGranularity | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_branch_storage import DatabaseBranchStorage
+ current_storage_bytes = self.current_storage_bytes
+
+ current_storage_mb = self.current_storage_mb
+
+ storage_bytes = self.storage_bytes
+
+ data_written_bytes = self.data_written_bytes
+
+ data_transfer_bytes = self.data_transfer_bytes
+
+ compute_time_seconds = self.compute_time_seconds
+
+ active_time_seconds = self.active_time_seconds
+
+ branches: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.branches, Unset):
+ branches = []
+ for branches_item_data in self.branches:
+ branches_item = branches_item_data.to_dict()
+ branches.append(branches_item)
+
+
+
+ time_range = self.time_range
+
+ granularity: str | Unset = UNSET
+ if not isinstance(self.granularity, Unset):
+ granularity = self.granularity
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "current_storage_bytes": current_storage_bytes,
+ "current_storage_mb": current_storage_mb,
+ "storage_bytes": storage_bytes,
+ "data_written_bytes": data_written_bytes,
+ "data_transfer_bytes": data_transfer_bytes,
+ "compute_time_seconds": compute_time_seconds,
+ "active_time_seconds": active_time_seconds,
+ })
+ if branches is not UNSET:
+ field_dict["branches"] = branches
+ if time_range is not UNSET:
+ field_dict["time_range"] = time_range
+ if granularity is not UNSET:
+ field_dict["granularity"] = granularity
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_branch_storage import DatabaseBranchStorage
+ d = dict(src_dict)
+ current_storage_bytes = d.pop("current_storage_bytes")
+
+ current_storage_mb = d.pop("current_storage_mb")
+
+ storage_bytes = d.pop("storage_bytes")
+
+ data_written_bytes = d.pop("data_written_bytes")
+
+ data_transfer_bytes = d.pop("data_transfer_bytes")
+
+ compute_time_seconds = d.pop("compute_time_seconds")
+
+ active_time_seconds = d.pop("active_time_seconds")
+
+ _branches = d.pop("branches", UNSET)
+ branches: list[DatabaseBranchStorage] | Unset = UNSET
+ if _branches is not UNSET:
+ branches = []
+ for branches_item_data in _branches:
+ branches_item = DatabaseBranchStorage.from_dict(branches_item_data)
+
+
+
+ branches.append(branches_item)
+
+
+ time_range = d.pop("time_range", UNSET)
+
+ _granularity = d.pop("granularity", UNSET)
+ granularity: DatabaseStatsGranularity | Unset
+ if isinstance(_granularity, Unset):
+ granularity = UNSET
+ else:
+ granularity = check_database_stats_granularity(_granularity)
+
+
+
+
+ database_stats = cls(
+ current_storage_bytes=current_storage_bytes,
+ current_storage_mb=current_storage_mb,
+ storage_bytes=storage_bytes,
+ data_written_bytes=data_written_bytes,
+ data_transfer_bytes=data_transfer_bytes,
+ compute_time_seconds=compute_time_seconds,
+ active_time_seconds=active_time_seconds,
+ branches=branches,
+ time_range=time_range,
+ granularity=granularity,
+ )
+
+
+ database_stats.additional_properties = d
+ return database_stats
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_stats_granularity.py b/src/volcano_sdk/_generated/models/database_stats_granularity.py
new file mode 100644
index 00000000..20bd4ef3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_stats_granularity.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DatabaseStatsGranularity = Literal['daily', 'hourly', 'monthly']
+
+DATABASE_STATS_GRANULARITY_VALUES: set[DatabaseStatsGranularity] = { 'daily', 'hourly', 'monthly', }
+
+def check_database_stats_granularity(value: str) -> DatabaseStatsGranularity:
+ if value in DATABASE_STATS_GRANULARITY_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DATABASE_STATS_GRANULARITY_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/database_status.py b/src/volcano_sdk/_generated/models/database_status.py
new file mode 100644
index 00000000..62c1fd29
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DatabaseStatus = Literal['active', 'deleting', 'failed', 'provisioning']
+
+DATABASE_STATUS_VALUES: set[DatabaseStatus] = { 'active', 'deleting', 'failed', 'provisioning', }
+
+def check_database_status(value: str) -> DatabaseStatus:
+ if value in DATABASE_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DATABASE_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/database_update_request.py b/src/volcano_sdk/_generated/models/database_update_request.py
new file mode 100644
index 00000000..81490b65
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_update_request.py
@@ -0,0 +1,120 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ from ..models.database_update_request_values import DatabaseUpdateRequestValues
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseUpdateRequest")
+
+
+
+@_attrs_define
+class DatabaseUpdateRequest:
+ """
+ Attributes:
+ table (str): Table name Example: posts.
+ values (DatabaseUpdateRequestValues): Column values to update Example: {'title': 'Updated Title', 'status':
+ 'published'}.
+ filters (list[DatabaseQueryFilter]): WHERE conditions for which rows to update. At least one filter is
+ required; a filterless update is rejected to avoid rewriting every
+ row.
+ Example: [{'column': 'id', 'operator': 'eq', 'value': 'post-uuid'}].
+ """
+
+ table: str
+ values: DatabaseUpdateRequestValues
+ filters: list[DatabaseQueryFilter]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ from ..models.database_update_request_values import DatabaseUpdateRequestValues
+ table = self.table
+
+ values = self.values.to_dict()
+
+ filters = []
+ for filters_item_data in self.filters:
+ filters_item = filters_item_data.to_dict()
+ filters.append(filters_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "table": table,
+ "values": values,
+ "filters": filters,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database_query_filter import DatabaseQueryFilter
+ from ..models.database_update_request_values import DatabaseUpdateRequestValues
+ d = dict(src_dict)
+ table = d.pop("table")
+
+ values = DatabaseUpdateRequestValues.from_dict(d.pop("values"))
+
+
+
+
+ filters = []
+ _filters = d.pop("filters")
+ for filters_item_data in (_filters):
+ filters_item = DatabaseQueryFilter.from_dict(filters_item_data)
+
+
+
+ filters.append(filters_item)
+
+
+ database_update_request = cls(
+ table=table,
+ values=values,
+ filters=filters,
+ )
+
+
+ database_update_request.additional_properties = d
+ return database_update_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/database_update_request_values.py b/src/volcano_sdk/_generated/models/database_update_request_values.py
new file mode 100644
index 00000000..155cc842
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/database_update_request_values.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="DatabaseUpdateRequestValues")
+
+
+
+@_attrs_define
+class DatabaseUpdateRequestValues:
+ """ Column values to update
+
+ Example:
+ {'title': 'Updated Title', 'status': 'published'}
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ database_update_request_values = cls(
+ )
+
+
+ database_update_request_values.additional_properties = d
+ return database_update_request_values
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/delete_database_branch_response_202.py b/src/volcano_sdk/_generated/models/delete_database_branch_response_202.py
new file mode 100644
index 00000000..6b5d882b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/delete_database_branch_response_202.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="DeleteDatabaseBranchResponse202")
+
+
+
+@_attrs_define
+class DeleteDatabaseBranchResponse202:
+ """
+ Attributes:
+ status (str): Example: deleting.
+ message (str): Example: branch deletion in progress.
+ """
+
+ status: str
+ message: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ status = self.status
+
+ message = self.message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "status": status,
+ "message": message,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ status = d.pop("status")
+
+ message = d.pop("message")
+
+ delete_database_branch_response_202 = cls(
+ status=status,
+ message=message,
+ )
+
+
+ delete_database_branch_response_202.additional_properties = d
+ return delete_database_branch_response_202
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/delete_database_response_202.py b/src/volcano_sdk/_generated/models/delete_database_response_202.py
new file mode 100644
index 00000000..7f1c4631
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/delete_database_response_202.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="DeleteDatabaseResponse202")
+
+
+
+@_attrs_define
+class DeleteDatabaseResponse202:
+ """
+ Attributes:
+ status (str | Unset): Example: deleting.
+ message (str | Unset): Example: database deletion in progress.
+ """
+
+ status: str | Unset = UNSET
+ message: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ status = self.status
+
+ message = self.message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if status is not UNSET:
+ field_dict["status"] = status
+ if message is not UNSET:
+ field_dict["message"] = message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ status = d.pop("status", UNSET)
+
+ message = d.pop("message", UNSET)
+
+ delete_database_response_202 = cls(
+ status=status,
+ message=message,
+ )
+
+
+ delete_database_response_202.additional_properties = d
+ return delete_database_response_202
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/delete_email_template_type.py b/src/volcano_sdk/_generated/models/delete_email_template_type.py
new file mode 100644
index 00000000..a845c562
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/delete_email_template_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DeleteEmailTemplateType = Literal['confirmation', 'password_changed', 'password_reset', 'welcome']
+
+DELETE_EMAIL_TEMPLATE_TYPE_VALUES: set[DeleteEmailTemplateType] = { 'confirmation', 'password_changed', 'password_reset', 'welcome', }
+
+def check_delete_email_template_type(value: str) -> DeleteEmailTemplateType:
+ if value in DELETE_EMAIL_TEMPLATE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DELETE_EMAIL_TEMPLATE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/delete_o_auth_config_provider.py b/src/volcano_sdk/_generated/models/delete_o_auth_config_provider.py
new file mode 100644
index 00000000..b375ba86
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/delete_o_auth_config_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DeleteOAuthConfigProvider = Literal['apple', 'device', 'github', 'google', 'microsoft']
+
+DELETE_O_AUTH_CONFIG_PROVIDER_VALUES: set[DeleteOAuthConfigProvider] = { 'apple', 'device', 'github', 'google', 'microsoft', }
+
+def check_delete_o_auth_config_provider(value: str) -> DeleteOAuthConfigProvider:
+ if value in DELETE_O_AUTH_CONFIG_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DELETE_O_AUTH_CONFIG_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/deployment_phase.py b/src/volcano_sdk/_generated/models/deployment_phase.py
new file mode 100644
index 00000000..655e73d5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/deployment_phase.py
@@ -0,0 +1,145 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.deployment_phase_name import check_deployment_phase_name
+from ..models.deployment_phase_name import DeploymentPhaseName
+from ..models.deployment_phase_status import check_deployment_phase_status
+from ..models.deployment_phase_status import DeploymentPhaseStatus
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="DeploymentPhase")
+
+
+
+@_attrs_define
+class DeploymentPhase:
+ """ Timing and outcome for one normalized deployment pipeline phase.
+
+ Attributes:
+ name (DeploymentPhaseName):
+ status (DeploymentPhaseStatus):
+ started_at (datetime.datetime | Unset):
+ completed_at (datetime.datetime | Unset):
+ duration_seconds (int | Unset):
+ """
+
+ name: DeploymentPhaseName
+ status: DeploymentPhaseStatus
+ started_at: datetime.datetime | Unset = UNSET
+ completed_at: datetime.datetime | Unset = UNSET
+ duration_seconds: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name: str = self.name
+
+ status: str = self.status
+
+ started_at: str | Unset = UNSET
+ if not isinstance(self.started_at, Unset):
+ started_at = self.started_at.isoformat()
+
+ completed_at: str | Unset = UNSET
+ if not isinstance(self.completed_at, Unset):
+ completed_at = self.completed_at.isoformat()
+
+ duration_seconds = self.duration_seconds
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "status": status,
+ })
+ if started_at is not UNSET:
+ field_dict["started_at"] = started_at
+ if completed_at is not UNSET:
+ field_dict["completed_at"] = completed_at
+ if duration_seconds is not UNSET:
+ field_dict["duration_seconds"] = duration_seconds
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = check_deployment_phase_name(d.pop("name"))
+
+
+
+
+ status = check_deployment_phase_status(d.pop("status"))
+
+
+
+
+ _started_at = d.pop("started_at", UNSET)
+ started_at: datetime.datetime | Unset
+ if isinstance(_started_at, Unset):
+ started_at = UNSET
+ else:
+ started_at = datetime.datetime.fromisoformat(_started_at)
+
+
+
+
+ _completed_at = d.pop("completed_at", UNSET)
+ completed_at: datetime.datetime | Unset
+ if isinstance(_completed_at, Unset):
+ completed_at = UNSET
+ else:
+ completed_at = datetime.datetime.fromisoformat(_completed_at)
+
+
+
+
+ duration_seconds = d.pop("duration_seconds", UNSET)
+
+ deployment_phase = cls(
+ name=name,
+ status=status,
+ started_at=started_at,
+ completed_at=completed_at,
+ duration_seconds=duration_seconds,
+ )
+
+
+ deployment_phase.additional_properties = d
+ return deployment_phase
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/deployment_phase_name.py b/src/volcano_sdk/_generated/models/deployment_phase_name.py
new file mode 100644
index 00000000..6c2b895b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/deployment_phase_name.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DeploymentPhaseName = Literal['build', 'checkout', 'image', 'provisioning', 'queue', 'rollout', 'verification']
+
+DEPLOYMENT_PHASE_NAME_VALUES: set[DeploymentPhaseName] = { 'build', 'checkout', 'image', 'provisioning', 'queue', 'rollout', 'verification', }
+
+def check_deployment_phase_name(value: str) -> DeploymentPhaseName:
+ if value in DEPLOYMENT_PHASE_NAME_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DEPLOYMENT_PHASE_NAME_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/deployment_phase_status.py b/src/volcano_sdk/_generated/models/deployment_phase_status.py
new file mode 100644
index 00000000..676caad2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/deployment_phase_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DeploymentPhaseStatus = Literal['failed', 'in_progress', 'pending', 'skipped', 'succeeded']
+
+DEPLOYMENT_PHASE_STATUS_VALUES: set[DeploymentPhaseStatus] = { 'failed', 'in_progress', 'pending', 'skipped', 'succeeded', }
+
+def check_deployment_phase_status(value: str) -> DeploymentPhaseStatus:
+ if value in DEPLOYMENT_PHASE_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DEPLOYMENT_PHASE_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/deployment_progress.py b/src/volcano_sdk/_generated/models/deployment_progress.py
new file mode 100644
index 00000000..4dbe8f9f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/deployment_progress.py
@@ -0,0 +1,168 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.deployment_progress_current_phase import check_deployment_progress_current_phase
+from ..models.deployment_progress_current_phase import DeploymentProgressCurrentPhase
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.deployment_phase import DeploymentPhase
+
+
+
+
+
+T = TypeVar("T", bound="DeploymentProgress")
+
+
+
+@_attrs_define
+class DeploymentProgress:
+ """ Normalized live progress derived from the deployment workflow and build phases.
+
+ Attributes:
+ started_at (datetime.datetime):
+ elapsed_seconds (int):
+ phases (list[DeploymentPhase]):
+ updated_at (datetime.datetime):
+ current_phase (DeploymentProgressCurrentPhase | Unset):
+ completed_at (datetime.datetime | Unset):
+ """
+
+ started_at: datetime.datetime
+ elapsed_seconds: int
+ phases: list[DeploymentPhase]
+ updated_at: datetime.datetime
+ current_phase: DeploymentProgressCurrentPhase | Unset = UNSET
+ completed_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.deployment_phase import DeploymentPhase
+ started_at = self.started_at.isoformat()
+
+ elapsed_seconds = self.elapsed_seconds
+
+ phases = []
+ for phases_item_data in self.phases:
+ phases_item = phases_item_data.to_dict()
+ phases.append(phases_item)
+
+
+
+ updated_at = self.updated_at.isoformat()
+
+ current_phase: str | Unset = UNSET
+ if not isinstance(self.current_phase, Unset):
+ current_phase = self.current_phase
+
+
+ completed_at: str | Unset = UNSET
+ if not isinstance(self.completed_at, Unset):
+ completed_at = self.completed_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "started_at": started_at,
+ "elapsed_seconds": elapsed_seconds,
+ "phases": phases,
+ "updated_at": updated_at,
+ })
+ if current_phase is not UNSET:
+ field_dict["current_phase"] = current_phase
+ if completed_at is not UNSET:
+ field_dict["completed_at"] = completed_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.deployment_phase import DeploymentPhase
+ d = dict(src_dict)
+ started_at = datetime.datetime.fromisoformat(d.pop("started_at"))
+
+
+
+
+ elapsed_seconds = d.pop("elapsed_seconds")
+
+ phases = []
+ _phases = d.pop("phases")
+ for phases_item_data in (_phases):
+ phases_item = DeploymentPhase.from_dict(phases_item_data)
+
+
+
+ phases.append(phases_item)
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ _current_phase = d.pop("current_phase", UNSET)
+ current_phase: DeploymentProgressCurrentPhase | Unset
+ if isinstance(_current_phase, Unset):
+ current_phase = UNSET
+ else:
+ current_phase = check_deployment_progress_current_phase(_current_phase)
+
+
+
+
+ _completed_at = d.pop("completed_at", UNSET)
+ completed_at: datetime.datetime | Unset
+ if isinstance(_completed_at, Unset):
+ completed_at = UNSET
+ else:
+ completed_at = datetime.datetime.fromisoformat(_completed_at)
+
+
+
+
+ deployment_progress = cls(
+ started_at=started_at,
+ elapsed_seconds=elapsed_seconds,
+ phases=phases,
+ updated_at=updated_at,
+ current_phase=current_phase,
+ completed_at=completed_at,
+ )
+
+
+ deployment_progress.additional_properties = d
+ return deployment_progress
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/deployment_progress_current_phase.py b/src/volcano_sdk/_generated/models/deployment_progress_current_phase.py
new file mode 100644
index 00000000..d00e6571
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/deployment_progress_current_phase.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+DeploymentProgressCurrentPhase = Literal['build', 'checkout', 'image', 'provisioning', 'queue', 'rollout', 'verification']
+
+DEPLOYMENT_PROGRESS_CURRENT_PHASE_VALUES: set[DeploymentProgressCurrentPhase] = { 'build', 'checkout', 'image', 'provisioning', 'queue', 'rollout', 'verification', }
+
+def check_deployment_progress_current_phase(value: str) -> DeploymentProgressCurrentPhase:
+ if value in DEPLOYMENT_PROGRESS_CURRENT_PHASE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {DEPLOYMENT_PROGRESS_CURRENT_PHASE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/deployment_reference.py b/src/volcano_sdk/_generated/models/deployment_reference.py
new file mode 100644
index 00000000..84741248
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/deployment_reference.py
@@ -0,0 +1,81 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="DeploymentReference")
+
+
+
+@_attrs_define
+class DeploymentReference:
+ """ Stable reference to a Volcano deployment run.
+
+ Attributes:
+ id (UUID):
+ """
+
+ id: UUID
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ deployment_reference = cls(
+ id=id,
+ )
+
+
+ deployment_reference.additional_properties = d
+ return deployment_reference
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/device_authorization_response.py b/src/volcano_sdk/_generated/models/device_authorization_response.py
new file mode 100644
index 00000000..6d8ff4c7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/device_authorization_response.py
@@ -0,0 +1,122 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="DeviceAuthorizationResponse")
+
+
+
+@_attrs_define
+class DeviceAuthorizationResponse:
+ """
+ Attributes:
+ device_code (str):
+ user_code (str):
+ verification_uri (str): Browser verification URL. Points at the project's managed device
+ approval page served by this API:
+ `/projects/{projectId}/auth/hosted?action=device&anon_key=...`.
+ Requires the project to have managed auth enabled and a default anon
+ key. A custom CLI may ignore this and direct users to its own
+ RFC 8628-compatible page instead (see the device-auth guide).
+ verification_uri_complete (str): Same as `verification_uri` but with the `user_code` prefilled
+ (`&user_code=...`). This is the URL most device clients open.
+ expires_in (int):
+ interval (int):
+ """
+
+ device_code: str
+ user_code: str
+ verification_uri: str
+ verification_uri_complete: str
+ expires_in: int
+ interval: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ device_code = self.device_code
+
+ user_code = self.user_code
+
+ verification_uri = self.verification_uri
+
+ verification_uri_complete = self.verification_uri_complete
+
+ expires_in = self.expires_in
+
+ interval = self.interval
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "device_code": device_code,
+ "user_code": user_code,
+ "verification_uri": verification_uri,
+ "verification_uri_complete": verification_uri_complete,
+ "expires_in": expires_in,
+ "interval": interval,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ device_code = d.pop("device_code")
+
+ user_code = d.pop("user_code")
+
+ verification_uri = d.pop("verification_uri")
+
+ verification_uri_complete = d.pop("verification_uri_complete")
+
+ expires_in = d.pop("expires_in")
+
+ interval = d.pop("interval")
+
+ device_authorization_response = cls(
+ device_code=device_code,
+ user_code=user_code,
+ verification_uri=verification_uri,
+ verification_uri_complete=verification_uri_complete,
+ expires_in=expires_in,
+ interval=interval,
+ )
+
+
+ device_authorization_response.additional_properties = d
+ return device_authorization_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/email_template.py b/src/volcano_sdk/_generated/models/email_template.py
new file mode 100644
index 00000000..cbb01b24
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/email_template.py
@@ -0,0 +1,186 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.email_template_template_type import check_email_template_template_type
+from ..models.email_template_template_type import EmailTemplateTemplateType
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="EmailTemplate")
+
+
+
+@_attrs_define
+class EmailTemplate:
+ """ Custom email template
+
+ Attributes:
+ template_type (EmailTemplateTemplateType):
+ subject (str): Example: Confirm your email address.
+ html_body (str): HTML template with placeholders
+ text_body (str): Plain text template with placeholders
+ id (UUID | Unset):
+ project_id (UUID | Unset):
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ template_type: EmailTemplateTemplateType
+ subject: str
+ html_body: str
+ text_body: str
+ id: UUID | Unset = UNSET
+ project_id: UUID | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ template_type: str = self.template_type
+
+ subject = self.subject
+
+ html_body = self.html_body
+
+ text_body = self.text_body
+
+ id: str | Unset = UNSET
+ if not isinstance(self.id, Unset):
+ id = str(self.id)
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "template_type": template_type,
+ "subject": subject,
+ "html_body": html_body,
+ "text_body": text_body,
+ })
+ if id is not UNSET:
+ field_dict["id"] = id
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ template_type = check_email_template_template_type(d.pop("template_type"))
+
+
+
+
+ subject = d.pop("subject")
+
+ html_body = d.pop("html_body")
+
+ text_body = d.pop("text_body")
+
+ _id = d.pop("id", UNSET)
+ id: UUID | Unset
+ if isinstance(_id, Unset):
+ id = UNSET
+ else:
+ id = UUID(_id)
+
+
+
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ email_template = cls(
+ template_type=template_type,
+ subject=subject,
+ html_body=html_body,
+ text_body=text_body,
+ id=id,
+ project_id=project_id,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ email_template.additional_properties = d
+ return email_template
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/email_template_template_type.py b/src/volcano_sdk/_generated/models/email_template_template_type.py
new file mode 100644
index 00000000..049f25ff
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/email_template_template_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+EmailTemplateTemplateType = Literal['confirmation', 'password_changed', 'password_reset', 'welcome']
+
+EMAIL_TEMPLATE_TEMPLATE_TYPE_VALUES: set[EmailTemplateTemplateType] = { 'confirmation', 'password_changed', 'password_reset', 'welcome', }
+
+def check_email_template_template_type(value: str) -> EmailTemplateTemplateType:
+ if value in EMAIL_TEMPLATE_TEMPLATE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {EMAIL_TEMPLATE_TEMPLATE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/error.py b/src/volcano_sdk/_generated/models/error.py
new file mode 100644
index 00000000..4595ac6a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/error.py
@@ -0,0 +1,86 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="Error")
+
+
+
+@_attrs_define
+class Error:
+ """
+ Attributes:
+ error (str):
+ code (str | Unset): Stable machine-readable error code when a specific recovery path is available.
+ """
+
+ error: str
+ code: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ error = self.error
+
+ code = self.code
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "error": error,
+ })
+ if code is not UNSET:
+ field_dict["code"] = code
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ error = d.pop("error")
+
+ code = d.pop("code", UNSET)
+
+ error = cls(
+ error=error,
+ code=code,
+ )
+
+
+ error.additional_properties = d
+ return error
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend.py b/src/volcano_sdk/_generated/models/frontend.py
new file mode 100644
index 00000000..061ec4fc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend.py
@@ -0,0 +1,293 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.frontend_custom_domain_status import check_frontend_custom_domain_status
+from ..models.frontend_custom_domain_status import FrontendCustomDomainStatus
+from ..models.frontend_framework import check_frontend_framework
+from ..models.frontend_framework import FrontendFramework
+from ..models.frontend_status import check_frontend_status
+from ..models.frontend_status import FrontendStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="Frontend")
+
+
+
+@_attrs_define
+class Frontend:
+ """
+ Attributes:
+ id (UUID):
+ project_id (UUID):
+ name (str):
+ framework (FrontendFramework):
+ status (FrontendStatus): Frontend lifecycle status. `degraded` means the regional runtime remains
+ available but edge synchronization exhausted its immediate retries; Volcano
+ retries edge recovery without rebuilding the frontend, and stops once a new
+ deployment is queued or the retry budget runs out, leaving the frontend
+ `degraded` until the next redeploy. A redeploy that fails over a serving
+ frontend stays `active` on the previous deployment, so `failed` means no
+ deployment is serving.
+ deployed_regions (list[str]):
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ app_root (str | Unset): Optional relative POSIX path from the uploaded archive root to the Next.js app that is
+ deployed.
+ provisioning_started_at (datetime.datetime | Unset): Timestamp when the current provisioning phase started
+ current_deployment_id (UUID | Unset): Identifier of the latest frontend deployment operation
+ pending_deployment_id (UUID | Unset): Newest queued deployment that will run after the current operation
+ site_url (str | Unset):
+ custom_domain (str | Unset): Active custom domain hostname when configured
+ custom_domain_status (FrontendCustomDomainStatus | Unset): Current custom domain lifecycle status
+ last_invoked_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ project_id: UUID
+ name: str
+ framework: FrontendFramework
+ status: FrontendStatus
+ deployed_regions: list[str]
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ app_root: str | Unset = UNSET
+ provisioning_started_at: datetime.datetime | Unset = UNSET
+ current_deployment_id: UUID | Unset = UNSET
+ pending_deployment_id: UUID | Unset = UNSET
+ site_url: str | Unset = UNSET
+ custom_domain: str | Unset = UNSET
+ custom_domain_status: FrontendCustomDomainStatus | Unset = UNSET
+ last_invoked_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ project_id = str(self.project_id)
+
+ name = self.name
+
+ framework: str = self.framework
+
+ status: str = self.status
+
+ deployed_regions = self.deployed_regions
+
+
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ app_root = self.app_root
+
+ provisioning_started_at: str | Unset = UNSET
+ if not isinstance(self.provisioning_started_at, Unset):
+ provisioning_started_at = self.provisioning_started_at.isoformat()
+
+ current_deployment_id: str | Unset = UNSET
+ if not isinstance(self.current_deployment_id, Unset):
+ current_deployment_id = str(self.current_deployment_id)
+
+ pending_deployment_id: str | Unset = UNSET
+ if not isinstance(self.pending_deployment_id, Unset):
+ pending_deployment_id = str(self.pending_deployment_id)
+
+ site_url = self.site_url
+
+ custom_domain = self.custom_domain
+
+ custom_domain_status: str | Unset = UNSET
+ if not isinstance(self.custom_domain_status, Unset):
+ custom_domain_status = self.custom_domain_status
+
+
+ last_invoked_at: str | Unset = UNSET
+ if not isinstance(self.last_invoked_at, Unset):
+ last_invoked_at = self.last_invoked_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "project_id": project_id,
+ "name": name,
+ "framework": framework,
+ "status": status,
+ "deployed_regions": deployed_regions,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if app_root is not UNSET:
+ field_dict["app_root"] = app_root
+ if provisioning_started_at is not UNSET:
+ field_dict["provisioning_started_at"] = provisioning_started_at
+ if current_deployment_id is not UNSET:
+ field_dict["current_deployment_id"] = current_deployment_id
+ if pending_deployment_id is not UNSET:
+ field_dict["pending_deployment_id"] = pending_deployment_id
+ if site_url is not UNSET:
+ field_dict["site_url"] = site_url
+ if custom_domain is not UNSET:
+ field_dict["custom_domain"] = custom_domain
+ if custom_domain_status is not UNSET:
+ field_dict["custom_domain_status"] = custom_domain_status
+ if last_invoked_at is not UNSET:
+ field_dict["last_invoked_at"] = last_invoked_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ name = d.pop("name")
+
+ framework = check_frontend_framework(d.pop("framework"))
+
+
+
+
+ status = check_frontend_status(d.pop("status"))
+
+
+
+
+ deployed_regions = cast(list[str], d.pop("deployed_regions"))
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ app_root = d.pop("app_root", UNSET)
+
+ _provisioning_started_at = d.pop("provisioning_started_at", UNSET)
+ provisioning_started_at: datetime.datetime | Unset
+ if isinstance(_provisioning_started_at, Unset):
+ provisioning_started_at = UNSET
+ else:
+ provisioning_started_at = datetime.datetime.fromisoformat(_provisioning_started_at)
+
+
+
+
+ _current_deployment_id = d.pop("current_deployment_id", UNSET)
+ current_deployment_id: UUID | Unset
+ if isinstance(_current_deployment_id, Unset):
+ current_deployment_id = UNSET
+ else:
+ current_deployment_id = UUID(_current_deployment_id)
+
+
+
+
+ _pending_deployment_id = d.pop("pending_deployment_id", UNSET)
+ pending_deployment_id: UUID | Unset
+ if isinstance(_pending_deployment_id, Unset):
+ pending_deployment_id = UNSET
+ else:
+ pending_deployment_id = UUID(_pending_deployment_id)
+
+
+
+
+ site_url = d.pop("site_url", UNSET)
+
+ custom_domain = d.pop("custom_domain", UNSET)
+
+ _custom_domain_status = d.pop("custom_domain_status", UNSET)
+ custom_domain_status: FrontendCustomDomainStatus | Unset
+ if isinstance(_custom_domain_status, Unset):
+ custom_domain_status = UNSET
+ else:
+ custom_domain_status = check_frontend_custom_domain_status(_custom_domain_status)
+
+
+
+
+ _last_invoked_at = d.pop("last_invoked_at", UNSET)
+ last_invoked_at: datetime.datetime | Unset
+ if isinstance(_last_invoked_at, Unset):
+ last_invoked_at = UNSET
+ else:
+ last_invoked_at = datetime.datetime.fromisoformat(_last_invoked_at)
+
+
+
+
+ frontend = cls(
+ id=id,
+ project_id=project_id,
+ name=name,
+ framework=framework,
+ status=status,
+ deployed_regions=deployed_regions,
+ created_at=created_at,
+ updated_at=updated_at,
+ app_root=app_root,
+ provisioning_started_at=provisioning_started_at,
+ current_deployment_id=current_deployment_id,
+ pending_deployment_id=pending_deployment_id,
+ site_url=site_url,
+ custom_domain=custom_domain,
+ custom_domain_status=custom_domain_status,
+ last_invoked_at=last_invoked_at,
+ )
+
+
+ frontend.additional_properties = d
+ return frontend
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_custom_domain_response.py b/src/volcano_sdk/_generated/models/frontend_custom_domain_response.py
new file mode 100644
index 00000000..3c8ebdf1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_custom_domain_response.py
@@ -0,0 +1,203 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.frontend_custom_domain_response_domain_status import check_frontend_custom_domain_response_domain_status
+from ..models.frontend_custom_domain_response_domain_status import FrontendCustomDomainResponseDomainStatus
+from ..models.frontend_custom_domain_response_tls_mode import check_frontend_custom_domain_response_tls_mode
+from ..models.frontend_custom_domain_response_tls_mode import FrontendCustomDomainResponseTlsMode
+from ..models.frontend_custom_domain_response_verification_status import check_frontend_custom_domain_response_verification_status
+from ..models.frontend_custom_domain_response_verification_status import FrontendCustomDomainResponseVerificationStatus
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.frontend_domain_routing_record import FrontendDomainRoutingRecord
+ from ..models.frontend_domain_verification_record import FrontendDomainVerificationRecord
+
+
+
+
+
+T = TypeVar("T", bound="FrontendCustomDomainResponse")
+
+
+
+@_attrs_define
+class FrontendCustomDomainResponse:
+ """
+ Attributes:
+ domain (str):
+ tls_mode (FrontendCustomDomainResponseTlsMode):
+ domain_status (FrontendCustomDomainResponseDomainStatus):
+ verification_status (FrontendCustomDomainResponseVerificationStatus):
+ effective_urls (list[str]):
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ verification_records (list[FrontendDomainVerificationRecord] | Unset):
+ required_routing_record (FrontendDomainRoutingRecord | Unset):
+ """
+
+ domain: str
+ tls_mode: FrontendCustomDomainResponseTlsMode
+ domain_status: FrontendCustomDomainResponseDomainStatus
+ verification_status: FrontendCustomDomainResponseVerificationStatus
+ effective_urls: list[str]
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ verification_records: list[FrontendDomainVerificationRecord] | Unset = UNSET
+ required_routing_record: FrontendDomainRoutingRecord | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend_domain_routing_record import FrontendDomainRoutingRecord
+ from ..models.frontend_domain_verification_record import FrontendDomainVerificationRecord
+ domain = self.domain
+
+ tls_mode: str = self.tls_mode
+
+ domain_status: str = self.domain_status
+
+ verification_status: str = self.verification_status
+
+ effective_urls = self.effective_urls
+
+
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ verification_records: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.verification_records, Unset):
+ verification_records = []
+ for verification_records_item_data in self.verification_records:
+ verification_records_item = verification_records_item_data.to_dict()
+ verification_records.append(verification_records_item)
+
+
+
+ required_routing_record: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.required_routing_record, Unset):
+ required_routing_record = self.required_routing_record.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "domain": domain,
+ "tls_mode": tls_mode,
+ "domain_status": domain_status,
+ "verification_status": verification_status,
+ "effective_urls": effective_urls,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if verification_records is not UNSET:
+ field_dict["verification_records"] = verification_records
+ if required_routing_record is not UNSET:
+ field_dict["required_routing_record"] = required_routing_record
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend_domain_routing_record import FrontendDomainRoutingRecord
+ from ..models.frontend_domain_verification_record import FrontendDomainVerificationRecord
+ d = dict(src_dict)
+ domain = d.pop("domain")
+
+ tls_mode = check_frontend_custom_domain_response_tls_mode(d.pop("tls_mode"))
+
+
+
+
+ domain_status = check_frontend_custom_domain_response_domain_status(d.pop("domain_status"))
+
+
+
+
+ verification_status = check_frontend_custom_domain_response_verification_status(d.pop("verification_status"))
+
+
+
+
+ effective_urls = cast(list[str], d.pop("effective_urls"))
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ _verification_records = d.pop("verification_records", UNSET)
+ verification_records: list[FrontendDomainVerificationRecord] | Unset = UNSET
+ if _verification_records is not UNSET:
+ verification_records = []
+ for verification_records_item_data in _verification_records:
+ verification_records_item = FrontendDomainVerificationRecord.from_dict(verification_records_item_data)
+
+
+
+ verification_records.append(verification_records_item)
+
+
+ _required_routing_record = d.pop("required_routing_record", UNSET)
+ required_routing_record: FrontendDomainRoutingRecord | Unset
+ if isinstance(_required_routing_record, Unset):
+ required_routing_record = UNSET
+ else:
+ required_routing_record = FrontendDomainRoutingRecord.from_dict(_required_routing_record)
+
+
+
+
+ frontend_custom_domain_response = cls(
+ domain=domain,
+ tls_mode=tls_mode,
+ domain_status=domain_status,
+ verification_status=verification_status,
+ effective_urls=effective_urls,
+ created_at=created_at,
+ updated_at=updated_at,
+ verification_records=verification_records,
+ required_routing_record=required_routing_record,
+ )
+
+
+ frontend_custom_domain_response.additional_properties = d
+ return frontend_custom_domain_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_custom_domain_response_domain_status.py b/src/volcano_sdk/_generated/models/frontend_custom_domain_response_domain_status.py
new file mode 100644
index 00000000..711efc52
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_custom_domain_response_domain_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendCustomDomainResponseDomainStatus = Literal['active', 'deleted', 'detaching', 'failed', 'pending_verification', 'provisioning']
+
+FRONTEND_CUSTOM_DOMAIN_RESPONSE_DOMAIN_STATUS_VALUES: set[FrontendCustomDomainResponseDomainStatus] = { 'active', 'deleted', 'detaching', 'failed', 'pending_verification', 'provisioning', }
+
+def check_frontend_custom_domain_response_domain_status(value: str) -> FrontendCustomDomainResponseDomainStatus:
+ if value in FRONTEND_CUSTOM_DOMAIN_RESPONSE_DOMAIN_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_CUSTOM_DOMAIN_RESPONSE_DOMAIN_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_custom_domain_response_tls_mode.py b/src/volcano_sdk/_generated/models/frontend_custom_domain_response_tls_mode.py
new file mode 100644
index 00000000..a6cc3ca2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_custom_domain_response_tls_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendCustomDomainResponseTlsMode = Literal['byoc', 'managed']
+
+FRONTEND_CUSTOM_DOMAIN_RESPONSE_TLS_MODE_VALUES: set[FrontendCustomDomainResponseTlsMode] = { 'byoc', 'managed', }
+
+def check_frontend_custom_domain_response_tls_mode(value: str) -> FrontendCustomDomainResponseTlsMode:
+ if value in FRONTEND_CUSTOM_DOMAIN_RESPONSE_TLS_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_CUSTOM_DOMAIN_RESPONSE_TLS_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_custom_domain_response_verification_status.py b/src/volcano_sdk/_generated/models/frontend_custom_domain_response_verification_status.py
new file mode 100644
index 00000000..2eee519a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_custom_domain_response_verification_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendCustomDomainResponseVerificationStatus = Literal['pending', 'verified']
+
+FRONTEND_CUSTOM_DOMAIN_RESPONSE_VERIFICATION_STATUS_VALUES: set[FrontendCustomDomainResponseVerificationStatus] = { 'pending', 'verified', }
+
+def check_frontend_custom_domain_response_verification_status(value: str) -> FrontendCustomDomainResponseVerificationStatus:
+ if value in FRONTEND_CUSTOM_DOMAIN_RESPONSE_VERIFICATION_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_CUSTOM_DOMAIN_RESPONSE_VERIFICATION_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_custom_domain_status.py b/src/volcano_sdk/_generated/models/frontend_custom_domain_status.py
new file mode 100644
index 00000000..1928f3d0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_custom_domain_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendCustomDomainStatus = Literal['active', 'deleted', 'detaching', 'failed', 'pending_verification', 'provisioning']
+
+FRONTEND_CUSTOM_DOMAIN_STATUS_VALUES: set[FrontendCustomDomainStatus] = { 'active', 'deleted', 'detaching', 'failed', 'pending_verification', 'provisioning', }
+
+def check_frontend_custom_domain_status(value: str) -> FrontendCustomDomainStatus:
+ if value in FRONTEND_CUSTOM_DOMAIN_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_CUSTOM_DOMAIN_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config.py b/src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config.py
new file mode 100644
index 00000000..73a39187
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config.py
@@ -0,0 +1,108 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.frontend_custom_domain_tls_config_mode import check_frontend_custom_domain_tls_config_mode
+from ..models.frontend_custom_domain_tls_config_mode import FrontendCustomDomainTLSConfigMode
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="FrontendCustomDomainTLSConfig")
+
+
+
+@_attrs_define
+class FrontendCustomDomainTLSConfig:
+ """
+ Attributes:
+ mode (FrontendCustomDomainTLSConfigMode): BYOC is mandatory for custom domain creation. Default: 'byoc'.
+ certificate_pem (str): Required. PEM-encoded certificate.
+ private_key_pem (str): Required. PEM-encoded private key.
+ certificate_chain_pem (str | Unset): Optional PEM-encoded certificate chain.
+ """
+
+ certificate_pem: str
+ private_key_pem: str
+ mode: FrontendCustomDomainTLSConfigMode = 'byoc'
+ certificate_chain_pem: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ mode: str = self.mode
+
+ certificate_pem = self.certificate_pem
+
+ private_key_pem = self.private_key_pem
+
+ certificate_chain_pem = self.certificate_chain_pem
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "mode": mode,
+ "certificate_pem": certificate_pem,
+ "private_key_pem": private_key_pem,
+ })
+ if certificate_chain_pem is not UNSET:
+ field_dict["certificate_chain_pem"] = certificate_chain_pem
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ mode = check_frontend_custom_domain_tls_config_mode(d.pop("mode"))
+
+
+
+
+ certificate_pem = d.pop("certificate_pem")
+
+ private_key_pem = d.pop("private_key_pem")
+
+ certificate_chain_pem = d.pop("certificate_chain_pem", UNSET)
+
+ frontend_custom_domain_tls_config = cls(
+ mode=mode,
+ certificate_pem=certificate_pem,
+ private_key_pem=private_key_pem,
+ certificate_chain_pem=certificate_chain_pem,
+ )
+
+
+ frontend_custom_domain_tls_config.additional_properties = d
+ return frontend_custom_domain_tls_config
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config_mode.py b/src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config_mode.py
new file mode 100644
index 00000000..32360945
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_custom_domain_tls_config_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendCustomDomainTLSConfigMode = Literal['byoc']
+
+FRONTEND_CUSTOM_DOMAIN_TLS_CONFIG_MODE_VALUES: set[FrontendCustomDomainTLSConfigMode] = { 'byoc', }
+
+def check_frontend_custom_domain_tls_config_mode(value: str) -> FrontendCustomDomainTLSConfigMode:
+ if value in FRONTEND_CUSTOM_DOMAIN_TLS_CONFIG_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_CUSTOM_DOMAIN_TLS_CONFIG_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_deployment.py b/src/volcano_sdk/_generated/models/frontend_deployment.py
new file mode 100644
index 00000000..d32efecc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_deployment.py
@@ -0,0 +1,304 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.frontend_deployment_deploy_source import check_frontend_deployment_deploy_source
+from ..models.frontend_deployment_deploy_source import FrontendDeploymentDeploySource
+from ..models.frontend_deployment_operation import check_frontend_deployment_operation
+from ..models.frontend_deployment_operation import FrontendDeploymentOperation
+from ..models.frontend_deployment_status import check_frontend_deployment_status
+from ..models.frontend_deployment_status import FrontendDeploymentStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.deployment_progress import DeploymentProgress
+
+
+
+
+
+T = TypeVar("T", bound="FrontendDeployment")
+
+
+
+@_attrs_define
+class FrontendDeployment:
+ """
+ Attributes:
+ id (UUID):
+ frontend_id (UUID):
+ project_id (UUID):
+ operation (FrontendDeploymentOperation):
+ status (FrontendDeploymentStatus): Deployment lifecycle status. A `degraded` redeploy remains available while
+ edge-only recovery is retried. A `failed` redeploy is recorded here while the
+ frontend keeps serving its previous deployment.
+ deploy_source (FrontendDeploymentDeploySource): What initiated this deployment.
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ initiated_by (str | Unset): Platform user that triggered a request-initiated deployment; absent for git and
+ system deployments.
+ artifact_bucket (str | Unset):
+ artifact_key (str | Unset):
+ artifact_version (str | Unset):
+ site_url (str | Unset):
+ cloudformation_stack_id (str | Unset):
+ cloudformation_stack_url (str | Unset):
+ codebuild_duration_seconds (int | Unset): Total CodeBuild build duration recorded for this deployment, in
+ seconds.
+ codebuild_build_count (int | Unset): Number of completed CodeBuild builds included in
+ codebuild_duration_seconds.
+ codebuild_duration_recorded_at (datetime.datetime | Unset):
+ progress (DeploymentProgress | Unset): Normalized live progress derived from the deployment workflow and build
+ phases.
+ error_message (str | Unset):
+ """
+
+ id: UUID
+ frontend_id: UUID
+ project_id: UUID
+ operation: FrontendDeploymentOperation
+ status: FrontendDeploymentStatus
+ deploy_source: FrontendDeploymentDeploySource
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ initiated_by: str | Unset = UNSET
+ artifact_bucket: str | Unset = UNSET
+ artifact_key: str | Unset = UNSET
+ artifact_version: str | Unset = UNSET
+ site_url: str | Unset = UNSET
+ cloudformation_stack_id: str | Unset = UNSET
+ cloudformation_stack_url: str | Unset = UNSET
+ codebuild_duration_seconds: int | Unset = UNSET
+ codebuild_build_count: int | Unset = UNSET
+ codebuild_duration_recorded_at: datetime.datetime | Unset = UNSET
+ progress: DeploymentProgress | Unset = UNSET
+ error_message: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.deployment_progress import DeploymentProgress
+ id = str(self.id)
+
+ frontend_id = str(self.frontend_id)
+
+ project_id = str(self.project_id)
+
+ operation: str = self.operation
+
+ status: str = self.status
+
+ deploy_source: str = self.deploy_source
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ initiated_by = self.initiated_by
+
+ artifact_bucket = self.artifact_bucket
+
+ artifact_key = self.artifact_key
+
+ artifact_version = self.artifact_version
+
+ site_url = self.site_url
+
+ cloudformation_stack_id = self.cloudformation_stack_id
+
+ cloudformation_stack_url = self.cloudformation_stack_url
+
+ codebuild_duration_seconds = self.codebuild_duration_seconds
+
+ codebuild_build_count = self.codebuild_build_count
+
+ codebuild_duration_recorded_at: str | Unset = UNSET
+ if not isinstance(self.codebuild_duration_recorded_at, Unset):
+ codebuild_duration_recorded_at = self.codebuild_duration_recorded_at.isoformat()
+
+ progress: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.progress, Unset):
+ progress = self.progress.to_dict()
+
+ error_message = self.error_message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "frontend_id": frontend_id,
+ "project_id": project_id,
+ "operation": operation,
+ "status": status,
+ "deploy_source": deploy_source,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if initiated_by is not UNSET:
+ field_dict["initiated_by"] = initiated_by
+ if artifact_bucket is not UNSET:
+ field_dict["artifact_bucket"] = artifact_bucket
+ if artifact_key is not UNSET:
+ field_dict["artifact_key"] = artifact_key
+ if artifact_version is not UNSET:
+ field_dict["artifact_version"] = artifact_version
+ if site_url is not UNSET:
+ field_dict["site_url"] = site_url
+ if cloudformation_stack_id is not UNSET:
+ field_dict["cloudformation_stack_id"] = cloudformation_stack_id
+ if cloudformation_stack_url is not UNSET:
+ field_dict["cloudformation_stack_url"] = cloudformation_stack_url
+ if codebuild_duration_seconds is not UNSET:
+ field_dict["codebuild_duration_seconds"] = codebuild_duration_seconds
+ if codebuild_build_count is not UNSET:
+ field_dict["codebuild_build_count"] = codebuild_build_count
+ if codebuild_duration_recorded_at is not UNSET:
+ field_dict["codebuild_duration_recorded_at"] = codebuild_duration_recorded_at
+ if progress is not UNSET:
+ field_dict["progress"] = progress
+ if error_message is not UNSET:
+ field_dict["error_message"] = error_message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.deployment_progress import DeploymentProgress
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ frontend_id = UUID(d.pop("frontend_id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ operation = check_frontend_deployment_operation(d.pop("operation"))
+
+
+
+
+ status = check_frontend_deployment_status(d.pop("status"))
+
+
+
+
+ deploy_source = check_frontend_deployment_deploy_source(d.pop("deploy_source"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ initiated_by = d.pop("initiated_by", UNSET)
+
+ artifact_bucket = d.pop("artifact_bucket", UNSET)
+
+ artifact_key = d.pop("artifact_key", UNSET)
+
+ artifact_version = d.pop("artifact_version", UNSET)
+
+ site_url = d.pop("site_url", UNSET)
+
+ cloudformation_stack_id = d.pop("cloudformation_stack_id", UNSET)
+
+ cloudformation_stack_url = d.pop("cloudformation_stack_url", UNSET)
+
+ codebuild_duration_seconds = d.pop("codebuild_duration_seconds", UNSET)
+
+ codebuild_build_count = d.pop("codebuild_build_count", UNSET)
+
+ _codebuild_duration_recorded_at = d.pop("codebuild_duration_recorded_at", UNSET)
+ codebuild_duration_recorded_at: datetime.datetime | Unset
+ if isinstance(_codebuild_duration_recorded_at, Unset):
+ codebuild_duration_recorded_at = UNSET
+ else:
+ codebuild_duration_recorded_at = datetime.datetime.fromisoformat(_codebuild_duration_recorded_at)
+
+
+
+
+ _progress = d.pop("progress", UNSET)
+ progress: DeploymentProgress | Unset
+ if isinstance(_progress, Unset):
+ progress = UNSET
+ else:
+ progress = DeploymentProgress.from_dict(_progress)
+
+
+
+
+ error_message = d.pop("error_message", UNSET)
+
+ frontend_deployment = cls(
+ id=id,
+ frontend_id=frontend_id,
+ project_id=project_id,
+ operation=operation,
+ status=status,
+ deploy_source=deploy_source,
+ created_at=created_at,
+ updated_at=updated_at,
+ initiated_by=initiated_by,
+ artifact_bucket=artifact_bucket,
+ artifact_key=artifact_key,
+ artifact_version=artifact_version,
+ site_url=site_url,
+ cloudformation_stack_id=cloudformation_stack_id,
+ cloudformation_stack_url=cloudformation_stack_url,
+ codebuild_duration_seconds=codebuild_duration_seconds,
+ codebuild_build_count=codebuild_build_count,
+ codebuild_duration_recorded_at=codebuild_duration_recorded_at,
+ progress=progress,
+ error_message=error_message,
+ )
+
+
+ frontend_deployment.additional_properties = d
+ return frontend_deployment
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_deployment_deploy_source.py b/src/volcano_sdk/_generated/models/frontend_deployment_deploy_source.py
new file mode 100644
index 00000000..10017bde
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_deployment_deploy_source.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendDeploymentDeploySource = Literal['api', 'cli', 'git', 'system', 'unknown', 'web']
+
+FRONTEND_DEPLOYMENT_DEPLOY_SOURCE_VALUES: set[FrontendDeploymentDeploySource] = { 'api', 'cli', 'git', 'system', 'unknown', 'web', }
+
+def check_frontend_deployment_deploy_source(value: str) -> FrontendDeploymentDeploySource:
+ if value in FRONTEND_DEPLOYMENT_DEPLOY_SOURCE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_DEPLOYMENT_DEPLOY_SOURCE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_deployment_operation.py b/src/volcano_sdk/_generated/models/frontend_deployment_operation.py
new file mode 100644
index 00000000..84b79edf
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_deployment_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendDeploymentOperation = Literal['delete', 'deploy', 'redeploy']
+
+FRONTEND_DEPLOYMENT_OPERATION_VALUES: set[FrontendDeploymentOperation] = { 'delete', 'deploy', 'redeploy', }
+
+def check_frontend_deployment_operation(value: str) -> FrontendDeploymentOperation:
+ if value in FRONTEND_DEPLOYMENT_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_DEPLOYMENT_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_deployment_status.py b/src/volcano_sdk/_generated/models/frontend_deployment_status.py
new file mode 100644
index 00000000..ad4e79c9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_deployment_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendDeploymentStatus = Literal['active', 'degraded', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded']
+
+FRONTEND_DEPLOYMENT_STATUS_VALUES: set[FrontendDeploymentStatus] = { 'active', 'degraded', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded', }
+
+def check_frontend_deployment_status(value: str) -> FrontendDeploymentStatus:
+ if value in FRONTEND_DEPLOYMENT_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_DEPLOYMENT_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_domain_routing_record.py b/src/volcano_sdk/_generated/models/frontend_domain_routing_record.py
new file mode 100644
index 00000000..d4cc2326
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_domain_routing_record.py
@@ -0,0 +1,98 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.frontend_domain_routing_record_record_type import check_frontend_domain_routing_record_record_type
+from ..models.frontend_domain_routing_record_record_type import FrontendDomainRoutingRecordRecordType
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="FrontendDomainRoutingRecord")
+
+
+
+@_attrs_define
+class FrontendDomainRoutingRecord:
+ """
+ Attributes:
+ record_type (FrontendDomainRoutingRecordRecordType):
+ name (str):
+ value (str):
+ """
+
+ record_type: FrontendDomainRoutingRecordRecordType
+ name: str
+ value: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ record_type: str = self.record_type
+
+ name = self.name
+
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "record_type": record_type,
+ "name": name,
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ record_type = check_frontend_domain_routing_record_record_type(d.pop("record_type"))
+
+
+
+
+ name = d.pop("name")
+
+ value = d.pop("value")
+
+ frontend_domain_routing_record = cls(
+ record_type=record_type,
+ name=name,
+ value=value,
+ )
+
+
+ frontend_domain_routing_record.additional_properties = d
+ return frontend_domain_routing_record
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_domain_routing_record_record_type.py b/src/volcano_sdk/_generated/models/frontend_domain_routing_record_record_type.py
new file mode 100644
index 00000000..8ea2715a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_domain_routing_record_record_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendDomainRoutingRecordRecordType = Literal['CNAME']
+
+FRONTEND_DOMAIN_ROUTING_RECORD_RECORD_TYPE_VALUES: set[FrontendDomainRoutingRecordRecordType] = { 'CNAME', }
+
+def check_frontend_domain_routing_record_record_type(value: str) -> FrontendDomainRoutingRecordRecordType:
+ if value in FRONTEND_DOMAIN_ROUTING_RECORD_RECORD_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_DOMAIN_ROUTING_RECORD_RECORD_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_domain_verification_record.py b/src/volcano_sdk/_generated/models/frontend_domain_verification_record.py
new file mode 100644
index 00000000..688bce99
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_domain_verification_record.py
@@ -0,0 +1,92 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="FrontendDomainVerificationRecord")
+
+
+
+@_attrs_define
+class FrontendDomainVerificationRecord:
+ """
+ Attributes:
+ name (str):
+ type_ (str):
+ value (str):
+ """
+
+ name: str
+ type_: str
+ value: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ type_ = self.type_
+
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "type": type_,
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ type_ = d.pop("type")
+
+ value = d.pop("value")
+
+ frontend_domain_verification_record = cls(
+ name=name,
+ type_=type_,
+ value=value,
+ )
+
+
+ frontend_domain_verification_record.additional_properties = d
+ return frontend_domain_verification_record
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_framework.py b/src/volcano_sdk/_generated/models/frontend_framework.py
new file mode 100644
index 00000000..2fac6087
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_framework.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendFramework = Literal['nextjs']
+
+FRONTEND_FRAMEWORK_VALUES: set[FrontendFramework] = { 'nextjs', }
+
+def check_frontend_framework(value: str) -> FrontendFramework:
+ if value in FRONTEND_FRAMEWORK_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_FRAMEWORK_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_status.py b/src/volcano_sdk/_generated/models/frontend_status.py
new file mode 100644
index 00000000..aed2a019
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FrontendStatus = Literal['active', 'degraded', 'deleting', 'failed', 'provisioning']
+
+FRONTEND_STATUS_VALUES: set[FrontendStatus] = { 'active', 'degraded', 'deleting', 'failed', 'provisioning', }
+
+def check_frontend_status(value: str) -> FrontendStatus:
+ if value in FRONTEND_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FRONTEND_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/frontend_usage_daily_entry.py b/src/volcano_sdk/_generated/models/frontend_usage_daily_entry.py
new file mode 100644
index 00000000..0afb7f3e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_usage_daily_entry.py
@@ -0,0 +1,107 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="FrontendUsageDailyEntry")
+
+
+
+@_attrs_define
+class FrontendUsageDailyEntry:
+ """ One day of request and error counts for a single frontend.
+
+ Attributes:
+ day (datetime.date): UTC date (YYYY-MM-DD) the counts cover.
+ requests (int): Total requests served on this day.
+ errors (int): 5xx responses served on this day.
+ page_views (int): Navigable-document responses served on this day (text/html or Sec-Fetch-Dest=document) —
+ strict subset of `requests`.
+ """
+
+ day: datetime.date
+ requests: int
+ errors: int
+ page_views: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ day = self.day.isoformat()
+
+ requests = self.requests
+
+ errors = self.errors
+
+ page_views = self.page_views
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "day": day,
+ "requests": requests,
+ "errors": errors,
+ "page_views": page_views,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ day = datetime.date.fromisoformat(d.pop("day"))
+
+
+
+
+ requests = d.pop("requests")
+
+ errors = d.pop("errors")
+
+ page_views = d.pop("page_views")
+
+ frontend_usage_daily_entry = cls(
+ day=day,
+ requests=requests,
+ errors=errors,
+ page_views=page_views,
+ )
+
+
+ frontend_usage_daily_entry.additional_properties = d
+ return frontend_usage_daily_entry
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_usage_data.py b/src/volcano_sdk/_generated/models/frontend_usage_data.py
new file mode 100644
index 00000000..99e97a67
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_usage_data.py
@@ -0,0 +1,112 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="FrontendUsageData")
+
+
+
+@_attrs_define
+class FrontendUsageData:
+ """ Monthly frontend request totals grouped by frontend.
+
+ Attributes:
+ frontend_id (UUID): Frontend ID
+ requests (int): Total requests for this frontend in the current usage month
+ frontend_name (None | str | Unset): Frontend name at the time usage was fetched
+ """
+
+ frontend_id: UUID
+ requests: int
+ frontend_name: None | str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ frontend_id = str(self.frontend_id)
+
+ requests = self.requests
+
+ frontend_name: None | str | Unset
+ if isinstance(self.frontend_name, Unset):
+ frontend_name = UNSET
+ else:
+ frontend_name = self.frontend_name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "frontend_id": frontend_id,
+ "requests": requests,
+ })
+ if frontend_name is not UNSET:
+ field_dict["frontend_name"] = frontend_name
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ frontend_id = UUID(d.pop("frontend_id"))
+
+
+
+
+ requests = d.pop("requests")
+
+ def _parse_frontend_name(data: object) -> None | str | Unset:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ return cast(None | str | Unset, data)
+
+ frontend_name = _parse_frontend_name(d.pop("frontend_name", UNSET))
+
+
+ frontend_usage_data = cls(
+ frontend_id=frontend_id,
+ requests=requests,
+ frontend_name=frontend_name,
+ )
+
+
+ frontend_usage_data.additional_properties = d
+ return frontend_usage_data
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/frontend_usage_history_response.py b/src/volcano_sdk/_generated/models/frontend_usage_history_response.py
new file mode 100644
index 00000000..eadfa466
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/frontend_usage_history_response.py
@@ -0,0 +1,139 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+from uuid import UUID
+
+if TYPE_CHECKING:
+ from ..models.frontend_usage_daily_entry import FrontendUsageDailyEntry
+
+
+
+
+
+T = TypeVar("T", bound="FrontendUsageHistoryResponse")
+
+
+
+@_attrs_define
+class FrontendUsageHistoryResponse:
+ """ Zero-filled daily series of request + error counts for a single frontend, oldest first.
+
+ Attributes:
+ frontend_id (UUID):
+ days (int): Number of daily entries returned (always equal to the `days` query param after clamping).
+ daily (list[FrontendUsageDailyEntry]):
+ total_requests (int):
+ total_errors (int):
+ total_page_views (int):
+ """
+
+ frontend_id: UUID
+ days: int
+ daily: list[FrontendUsageDailyEntry]
+ total_requests: int
+ total_errors: int
+ total_page_views: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend_usage_daily_entry import FrontendUsageDailyEntry
+ frontend_id = str(self.frontend_id)
+
+ days = self.days
+
+ daily = []
+ for daily_item_data in self.daily:
+ daily_item = daily_item_data.to_dict()
+ daily.append(daily_item)
+
+
+
+ total_requests = self.total_requests
+
+ total_errors = self.total_errors
+
+ total_page_views = self.total_page_views
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "frontend_id": frontend_id,
+ "days": days,
+ "daily": daily,
+ "total_requests": total_requests,
+ "total_errors": total_errors,
+ "total_page_views": total_page_views,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend_usage_daily_entry import FrontendUsageDailyEntry
+ d = dict(src_dict)
+ frontend_id = UUID(d.pop("frontend_id"))
+
+
+
+
+ days = d.pop("days")
+
+ daily = []
+ _daily = d.pop("daily")
+ for daily_item_data in (_daily):
+ daily_item = FrontendUsageDailyEntry.from_dict(daily_item_data)
+
+
+
+ daily.append(daily_item)
+
+
+ total_requests = d.pop("total_requests")
+
+ total_errors = d.pop("total_errors")
+
+ total_page_views = d.pop("total_page_views")
+
+ frontend_usage_history_response = cls(
+ frontend_id=frontend_id,
+ days=days,
+ daily=daily,
+ total_requests=total_requests,
+ total_errors=total_errors,
+ total_page_views=total_page_views,
+ )
+
+
+ frontend_usage_history_response.additional_properties = d
+ return frontend_usage_history_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function.py b/src/volcano_sdk/_generated/models/function.py
new file mode 100644
index 00000000..e257211d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function.py
@@ -0,0 +1,270 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.function_status import check_function_status
+from ..models.function_status import FunctionStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="Function")
+
+
+
+@_attrs_define
+class Function:
+ """
+ Attributes:
+ id (UUID):
+ project_id (UUID):
+ name (str):
+ status (FunctionStatus):
+ is_public (bool): Function visibility for anon-key invocation.
+ - `false` (default): only auth user tokens and service keys can invoke
+ - `true`: anon keys with `functions.invoke` can invoke
+ deployed_regions (list[str]): Regions where this function is currently deployed
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ provisioning_started_at (datetime.datetime | Unset): Timestamp when the current provisioning phase started
+ aws_function_arn (str | Unset):
+ invoke_url (str | Unset): Canonical GeoDNS endpoint URL for invoking this function (always HTTPS)
+ runtime (str | Unset):
+ handler (str | Unset):
+ current_deployment_id (UUID | Unset): Identifier of the latest function deployment operation
+ pending_deployment_id (UUID | Unset): Newest queued deployment that will run after the current operation
+ last_invoked_at (datetime.datetime | Unset): Most recent successful invocation timestamp
+ """
+
+ id: UUID
+ project_id: UUID
+ name: str
+ status: FunctionStatus
+ is_public: bool
+ deployed_regions: list[str]
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ provisioning_started_at: datetime.datetime | Unset = UNSET
+ aws_function_arn: str | Unset = UNSET
+ invoke_url: str | Unset = UNSET
+ runtime: str | Unset = UNSET
+ handler: str | Unset = UNSET
+ current_deployment_id: UUID | Unset = UNSET
+ pending_deployment_id: UUID | Unset = UNSET
+ last_invoked_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ project_id = str(self.project_id)
+
+ name = self.name
+
+ status: str = self.status
+
+ is_public = self.is_public
+
+ deployed_regions = self.deployed_regions
+
+
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ provisioning_started_at: str | Unset = UNSET
+ if not isinstance(self.provisioning_started_at, Unset):
+ provisioning_started_at = self.provisioning_started_at.isoformat()
+
+ aws_function_arn = self.aws_function_arn
+
+ invoke_url = self.invoke_url
+
+ runtime = self.runtime
+
+ handler = self.handler
+
+ current_deployment_id: str | Unset = UNSET
+ if not isinstance(self.current_deployment_id, Unset):
+ current_deployment_id = str(self.current_deployment_id)
+
+ pending_deployment_id: str | Unset = UNSET
+ if not isinstance(self.pending_deployment_id, Unset):
+ pending_deployment_id = str(self.pending_deployment_id)
+
+ last_invoked_at: str | Unset = UNSET
+ if not isinstance(self.last_invoked_at, Unset):
+ last_invoked_at = self.last_invoked_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "project_id": project_id,
+ "name": name,
+ "status": status,
+ "is_public": is_public,
+ "deployed_regions": deployed_regions,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if provisioning_started_at is not UNSET:
+ field_dict["provisioning_started_at"] = provisioning_started_at
+ if aws_function_arn is not UNSET:
+ field_dict["aws_function_arn"] = aws_function_arn
+ if invoke_url is not UNSET:
+ field_dict["invoke_url"] = invoke_url
+ if runtime is not UNSET:
+ field_dict["runtime"] = runtime
+ if handler is not UNSET:
+ field_dict["handler"] = handler
+ if current_deployment_id is not UNSET:
+ field_dict["current_deployment_id"] = current_deployment_id
+ if pending_deployment_id is not UNSET:
+ field_dict["pending_deployment_id"] = pending_deployment_id
+ if last_invoked_at is not UNSET:
+ field_dict["last_invoked_at"] = last_invoked_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ name = d.pop("name")
+
+ status = check_function_status(d.pop("status"))
+
+
+
+
+ is_public = d.pop("is_public")
+
+ deployed_regions = cast(list[str], d.pop("deployed_regions"))
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ _provisioning_started_at = d.pop("provisioning_started_at", UNSET)
+ provisioning_started_at: datetime.datetime | Unset
+ if isinstance(_provisioning_started_at, Unset):
+ provisioning_started_at = UNSET
+ else:
+ provisioning_started_at = datetime.datetime.fromisoformat(_provisioning_started_at)
+
+
+
+
+ aws_function_arn = d.pop("aws_function_arn", UNSET)
+
+ invoke_url = d.pop("invoke_url", UNSET)
+
+ runtime = d.pop("runtime", UNSET)
+
+ handler = d.pop("handler", UNSET)
+
+ _current_deployment_id = d.pop("current_deployment_id", UNSET)
+ current_deployment_id: UUID | Unset
+ if isinstance(_current_deployment_id, Unset):
+ current_deployment_id = UNSET
+ else:
+ current_deployment_id = UUID(_current_deployment_id)
+
+
+
+
+ _pending_deployment_id = d.pop("pending_deployment_id", UNSET)
+ pending_deployment_id: UUID | Unset
+ if isinstance(_pending_deployment_id, Unset):
+ pending_deployment_id = UNSET
+ else:
+ pending_deployment_id = UUID(_pending_deployment_id)
+
+
+
+
+ _last_invoked_at = d.pop("last_invoked_at", UNSET)
+ last_invoked_at: datetime.datetime | Unset
+ if isinstance(_last_invoked_at, Unset):
+ last_invoked_at = UNSET
+ else:
+ last_invoked_at = datetime.datetime.fromisoformat(_last_invoked_at)
+
+
+
+
+ function = cls(
+ id=id,
+ project_id=project_id,
+ name=name,
+ status=status,
+ is_public=is_public,
+ deployed_regions=deployed_regions,
+ created_at=created_at,
+ updated_at=updated_at,
+ provisioning_started_at=provisioning_started_at,
+ aws_function_arn=aws_function_arn,
+ invoke_url=invoke_url,
+ runtime=runtime,
+ handler=handler,
+ current_deployment_id=current_deployment_id,
+ pending_deployment_id=pending_deployment_id,
+ last_invoked_at=last_invoked_at,
+ )
+
+
+ function.additional_properties = d
+ return function
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_deployment.py b/src/volcano_sdk/_generated/models/function_deployment.py
new file mode 100644
index 00000000..4bdfa7b6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_deployment.py
@@ -0,0 +1,313 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.function_deployment_deploy_source import check_function_deployment_deploy_source
+from ..models.function_deployment_deploy_source import FunctionDeploymentDeploySource
+from ..models.function_deployment_operation import check_function_deployment_operation
+from ..models.function_deployment_operation import FunctionDeploymentOperation
+from ..models.function_deployment_status import check_function_deployment_status
+from ..models.function_deployment_status import FunctionDeploymentStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.deployment_progress import DeploymentProgress
+
+
+
+
+
+T = TypeVar("T", bound="FunctionDeployment")
+
+
+
+@_attrs_define
+class FunctionDeployment:
+ """
+ Attributes:
+ id (UUID):
+ function_id (UUID):
+ project_id (UUID):
+ operation (FunctionDeploymentOperation):
+ status (FunctionDeploymentStatus):
+ deploy_source (FunctionDeploymentDeploySource): What initiated this deployment.
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ batch_id (UUID | Unset):
+ initiated_by (str | Unset): Platform user that triggered a request-initiated deployment; absent for git and
+ system deployments.
+ artifact_bucket (str | Unset):
+ artifact_key (str | Unset):
+ artifact_version (str | Unset):
+ codebuild_duration_seconds (int | Unset): Total CodeBuild build duration recorded for this deployment, in
+ seconds.
+ codebuild_build_count (int | Unset): Number of completed CodeBuild builds included in
+ codebuild_duration_seconds.
+ codebuild_duration_recorded_at (datetime.datetime | Unset):
+ progress (DeploymentProgress | Unset): Normalized live progress derived from the deployment workflow and build
+ phases.
+ error_message (str | Unset):
+ completed_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ function_id: UUID
+ project_id: UUID
+ operation: FunctionDeploymentOperation
+ status: FunctionDeploymentStatus
+ deploy_source: FunctionDeploymentDeploySource
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ batch_id: UUID | Unset = UNSET
+ initiated_by: str | Unset = UNSET
+ artifact_bucket: str | Unset = UNSET
+ artifact_key: str | Unset = UNSET
+ artifact_version: str | Unset = UNSET
+ codebuild_duration_seconds: int | Unset = UNSET
+ codebuild_build_count: int | Unset = UNSET
+ codebuild_duration_recorded_at: datetime.datetime | Unset = UNSET
+ progress: DeploymentProgress | Unset = UNSET
+ error_message: str | Unset = UNSET
+ completed_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.deployment_progress import DeploymentProgress
+ id = str(self.id)
+
+ function_id = str(self.function_id)
+
+ project_id = str(self.project_id)
+
+ operation: str = self.operation
+
+ status: str = self.status
+
+ deploy_source: str = self.deploy_source
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ batch_id: str | Unset = UNSET
+ if not isinstance(self.batch_id, Unset):
+ batch_id = str(self.batch_id)
+
+ initiated_by = self.initiated_by
+
+ artifact_bucket = self.artifact_bucket
+
+ artifact_key = self.artifact_key
+
+ artifact_version = self.artifact_version
+
+ codebuild_duration_seconds = self.codebuild_duration_seconds
+
+ codebuild_build_count = self.codebuild_build_count
+
+ codebuild_duration_recorded_at: str | Unset = UNSET
+ if not isinstance(self.codebuild_duration_recorded_at, Unset):
+ codebuild_duration_recorded_at = self.codebuild_duration_recorded_at.isoformat()
+
+ progress: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.progress, Unset):
+ progress = self.progress.to_dict()
+
+ error_message = self.error_message
+
+ completed_at: str | Unset = UNSET
+ if not isinstance(self.completed_at, Unset):
+ completed_at = self.completed_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "function_id": function_id,
+ "project_id": project_id,
+ "operation": operation,
+ "status": status,
+ "deploy_source": deploy_source,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if batch_id is not UNSET:
+ field_dict["batch_id"] = batch_id
+ if initiated_by is not UNSET:
+ field_dict["initiated_by"] = initiated_by
+ if artifact_bucket is not UNSET:
+ field_dict["artifact_bucket"] = artifact_bucket
+ if artifact_key is not UNSET:
+ field_dict["artifact_key"] = artifact_key
+ if artifact_version is not UNSET:
+ field_dict["artifact_version"] = artifact_version
+ if codebuild_duration_seconds is not UNSET:
+ field_dict["codebuild_duration_seconds"] = codebuild_duration_seconds
+ if codebuild_build_count is not UNSET:
+ field_dict["codebuild_build_count"] = codebuild_build_count
+ if codebuild_duration_recorded_at is not UNSET:
+ field_dict["codebuild_duration_recorded_at"] = codebuild_duration_recorded_at
+ if progress is not UNSET:
+ field_dict["progress"] = progress
+ if error_message is not UNSET:
+ field_dict["error_message"] = error_message
+ if completed_at is not UNSET:
+ field_dict["completed_at"] = completed_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.deployment_progress import DeploymentProgress
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ function_id = UUID(d.pop("function_id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ operation = check_function_deployment_operation(d.pop("operation"))
+
+
+
+
+ status = check_function_deployment_status(d.pop("status"))
+
+
+
+
+ deploy_source = check_function_deployment_deploy_source(d.pop("deploy_source"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ _batch_id = d.pop("batch_id", UNSET)
+ batch_id: UUID | Unset
+ if isinstance(_batch_id, Unset):
+ batch_id = UNSET
+ else:
+ batch_id = UUID(_batch_id)
+
+
+
+
+ initiated_by = d.pop("initiated_by", UNSET)
+
+ artifact_bucket = d.pop("artifact_bucket", UNSET)
+
+ artifact_key = d.pop("artifact_key", UNSET)
+
+ artifact_version = d.pop("artifact_version", UNSET)
+
+ codebuild_duration_seconds = d.pop("codebuild_duration_seconds", UNSET)
+
+ codebuild_build_count = d.pop("codebuild_build_count", UNSET)
+
+ _codebuild_duration_recorded_at = d.pop("codebuild_duration_recorded_at", UNSET)
+ codebuild_duration_recorded_at: datetime.datetime | Unset
+ if isinstance(_codebuild_duration_recorded_at, Unset):
+ codebuild_duration_recorded_at = UNSET
+ else:
+ codebuild_duration_recorded_at = datetime.datetime.fromisoformat(_codebuild_duration_recorded_at)
+
+
+
+
+ _progress = d.pop("progress", UNSET)
+ progress: DeploymentProgress | Unset
+ if isinstance(_progress, Unset):
+ progress = UNSET
+ else:
+ progress = DeploymentProgress.from_dict(_progress)
+
+
+
+
+ error_message = d.pop("error_message", UNSET)
+
+ _completed_at = d.pop("completed_at", UNSET)
+ completed_at: datetime.datetime | Unset
+ if isinstance(_completed_at, Unset):
+ completed_at = UNSET
+ else:
+ completed_at = datetime.datetime.fromisoformat(_completed_at)
+
+
+
+
+ function_deployment = cls(
+ id=id,
+ function_id=function_id,
+ project_id=project_id,
+ operation=operation,
+ status=status,
+ deploy_source=deploy_source,
+ created_at=created_at,
+ updated_at=updated_at,
+ batch_id=batch_id,
+ initiated_by=initiated_by,
+ artifact_bucket=artifact_bucket,
+ artifact_key=artifact_key,
+ artifact_version=artifact_version,
+ codebuild_duration_seconds=codebuild_duration_seconds,
+ codebuild_build_count=codebuild_build_count,
+ codebuild_duration_recorded_at=codebuild_duration_recorded_at,
+ progress=progress,
+ error_message=error_message,
+ completed_at=completed_at,
+ )
+
+
+ function_deployment.additional_properties = d
+ return function_deployment
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_deployment_deploy_source.py b/src/volcano_sdk/_generated/models/function_deployment_deploy_source.py
new file mode 100644
index 00000000..5090e97a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_deployment_deploy_source.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FunctionDeploymentDeploySource = Literal['api', 'cli', 'git', 'system', 'unknown', 'web']
+
+FUNCTION_DEPLOYMENT_DEPLOY_SOURCE_VALUES: set[FunctionDeploymentDeploySource] = { 'api', 'cli', 'git', 'system', 'unknown', 'web', }
+
+def check_function_deployment_deploy_source(value: str) -> FunctionDeploymentDeploySource:
+ if value in FUNCTION_DEPLOYMENT_DEPLOY_SOURCE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FUNCTION_DEPLOYMENT_DEPLOY_SOURCE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/function_deployment_operation.py b/src/volcano_sdk/_generated/models/function_deployment_operation.py
new file mode 100644
index 00000000..90627608
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_deployment_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FunctionDeploymentOperation = Literal['delete', 'deploy', 'update']
+
+FUNCTION_DEPLOYMENT_OPERATION_VALUES: set[FunctionDeploymentOperation] = { 'delete', 'deploy', 'update', }
+
+def check_function_deployment_operation(value: str) -> FunctionDeploymentOperation:
+ if value in FUNCTION_DEPLOYMENT_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FUNCTION_DEPLOYMENT_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/function_deployment_status.py b/src/volcano_sdk/_generated/models/function_deployment_status.py
new file mode 100644
index 00000000..c120bfcc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_deployment_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FunctionDeploymentStatus = Literal['active', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded']
+
+FUNCTION_DEPLOYMENT_STATUS_VALUES: set[FunctionDeploymentStatus] = { 'active', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded', }
+
+def check_function_deployment_status(value: str) -> FunctionDeploymentStatus:
+ if value in FUNCTION_DEPLOYMENT_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FUNCTION_DEPLOYMENT_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/function_invocation_request.py b/src/volcano_sdk/_generated/models/function_invocation_request.py
new file mode 100644
index 00000000..86687373
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_invocation_request.py
@@ -0,0 +1,106 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.function_invocation_request_payload import FunctionInvocationRequestPayload
+
+
+
+
+
+T = TypeVar("T", bound="FunctionInvocationRequest")
+
+
+
+@_attrs_define
+class FunctionInvocationRequest:
+ """
+ Attributes:
+ payload (FunctionInvocationRequestPayload | Unset): Payload to send to the function.
+
+ If invoked with auth user token, Volcano automatically injects `__volcano_auth` context:
+ ```javascript
+ {
+ ...yourPayload,
+ __volcano_auth: {
+ user_id: "uuid",
+ email: "user@example.com",
+ project_id: "uuid",
+ role: "authenticated" | "anonymous"
+ }
+ }
+ ```
+ """
+
+ payload: FunctionInvocationRequestPayload | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.function_invocation_request_payload import FunctionInvocationRequestPayload
+ payload: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.payload, Unset):
+ payload = self.payload.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if payload is not UNSET:
+ field_dict["payload"] = payload
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.function_invocation_request_payload import FunctionInvocationRequestPayload
+ d = dict(src_dict)
+ _payload = d.pop("payload", UNSET)
+ payload: FunctionInvocationRequestPayload | Unset
+ if isinstance(_payload, Unset):
+ payload = UNSET
+ else:
+ payload = FunctionInvocationRequestPayload.from_dict(_payload)
+
+
+
+
+ function_invocation_request = cls(
+ payload=payload,
+ )
+
+
+ function_invocation_request.additional_properties = d
+ return function_invocation_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_invocation_request_payload.py b/src/volcano_sdk/_generated/models/function_invocation_request_payload.py
new file mode 100644
index 00000000..f9422124
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_invocation_request_payload.py
@@ -0,0 +1,79 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="FunctionInvocationRequestPayload")
+
+
+
+@_attrs_define
+class FunctionInvocationRequestPayload:
+ """ Payload to send to the function.
+
+ If invoked with auth user token, Volcano automatically injects `__volcano_auth` context:
+ ```javascript
+ {
+ ...yourPayload,
+ __volcano_auth: {
+ user_id: "uuid",
+ email: "user@example.com",
+ project_id: "uuid",
+ role: "authenticated" | "anonymous"
+ }
+ }
+ ```
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ function_invocation_request_payload = cls(
+ )
+
+
+ function_invocation_request_payload.additional_properties = d
+ return function_invocation_request_payload
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_invocation_response.py b/src/volcano_sdk/_generated/models/function_invocation_response.py
new file mode 100644
index 00000000..961e1370
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_invocation_response.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="FunctionInvocationResponse")
+
+
+
+@_attrs_define
+class FunctionInvocationResponse:
+ """ Raw function response body returned by the invoked function.
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ function_invocation_response = cls(
+ )
+
+
+ function_invocation_response.additional_properties = d
+ return function_invocation_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_region.py b/src/volcano_sdk/_generated/models/function_region.py
new file mode 100644
index 00000000..223d6cb1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_region.py
@@ -0,0 +1,92 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="FunctionRegion")
+
+
+
+@_attrs_define
+class FunctionRegion:
+ """
+ Attributes:
+ code (str): Region identifier accepted by function APIs. Example: us-east-1.
+ label (str): Human-readable region label suitable for display in pickers. Example: NA-East.
+ flag (str): Country flag emoji associated with the region's geography. Example: 🇺🇸.
+ """
+
+ code: str
+ label: str
+ flag: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ code = self.code
+
+ label = self.label
+
+ flag = self.flag
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "code": code,
+ "label": label,
+ "flag": flag,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ code = d.pop("code")
+
+ label = d.pop("label")
+
+ flag = d.pop("flag")
+
+ function_region = cls(
+ code=code,
+ label=label,
+ flag=flag,
+ )
+
+
+ function_region.additional_properties = d
+ return function_region
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_runtime_deployment.py b/src/volcano_sdk/_generated/models/function_runtime_deployment.py
new file mode 100644
index 00000000..ca197ab6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_runtime_deployment.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="FunctionRuntimeDeployment")
+
+
+
+@_attrs_define
+class FunctionRuntimeDeployment:
+ """
+ Attributes:
+ file_extensions (list[str]): Source file extensions the CLI can use to detect this runtime. Example: ['.js',
+ '.mjs'].
+ entrypoint (str): Archive path the CLI should use for a single-file function source. Example: index.js.
+ handler (str): Handler symbol the CLI should submit when deploying this runtime. Example: handler.
+ dependency_manifests (list[str]): Dependency manifest files the CLI should include for hosted builds. Example:
+ ['package.json', 'package-lock.json'].
+ """
+
+ file_extensions: list[str]
+ entrypoint: str
+ handler: str
+ dependency_manifests: list[str]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ file_extensions = self.file_extensions
+
+
+
+ entrypoint = self.entrypoint
+
+ handler = self.handler
+
+ dependency_manifests = self.dependency_manifests
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "file_extensions": file_extensions,
+ "entrypoint": entrypoint,
+ "handler": handler,
+ "dependency_manifests": dependency_manifests,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ file_extensions = cast(list[str], d.pop("file_extensions"))
+
+
+ entrypoint = d.pop("entrypoint")
+
+ handler = d.pop("handler")
+
+ dependency_manifests = cast(list[str], d.pop("dependency_manifests"))
+
+
+ function_runtime_deployment = cls(
+ file_extensions=file_extensions,
+ entrypoint=entrypoint,
+ handler=handler,
+ dependency_manifests=dependency_manifests,
+ )
+
+
+ function_runtime_deployment.additional_properties = d
+ return function_runtime_deployment
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_runtime_option.py b/src/volcano_sdk/_generated/models/function_runtime_option.py
new file mode 100644
index 00000000..6c94321b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_runtime_option.py
@@ -0,0 +1,108 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.function_runtime_deployment import FunctionRuntimeDeployment
+
+
+
+
+
+T = TypeVar("T", bound="FunctionRuntimeOption")
+
+
+
+@_attrs_define
+class FunctionRuntimeOption:
+ """
+ Attributes:
+ name (str): Runtime identifier accepted by function APIs. Example: nodejs24.x.
+ language (str): Runtime language family used by the CLI to choose defaults from source files. Example: nodejs.
+ default (bool): Whether this runtime is the CLI default for its language.
+ deployment (FunctionRuntimeDeployment):
+ """
+
+ name: str
+ language: str
+ default: bool
+ deployment: FunctionRuntimeDeployment
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.function_runtime_deployment import FunctionRuntimeDeployment
+ name = self.name
+
+ language = self.language
+
+ default = self.default
+
+ deployment = self.deployment.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "language": language,
+ "default": default,
+ "deployment": deployment,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.function_runtime_deployment import FunctionRuntimeDeployment
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ language = d.pop("language")
+
+ default = d.pop("default")
+
+ deployment = FunctionRuntimeDeployment.from_dict(d.pop("deployment"))
+
+
+
+
+ function_runtime_option = cls(
+ name=name,
+ language=language,
+ default=default,
+ deployment=deployment,
+ )
+
+
+ function_runtime_option.additional_properties = d
+ return function_runtime_option
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_runtimes_response.py b/src/volcano_sdk/_generated/models/function_runtimes_response.py
new file mode 100644
index 00000000..c5b3d457
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_runtimes_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.function_runtime_option import FunctionRuntimeOption
+
+
+
+
+
+T = TypeVar("T", bound="FunctionRuntimesResponse")
+
+
+
+@_attrs_define
+class FunctionRuntimesResponse:
+ """
+ Attributes:
+ runtimes (list[FunctionRuntimeOption]):
+ """
+
+ runtimes: list[FunctionRuntimeOption]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.function_runtime_option import FunctionRuntimeOption
+ runtimes = []
+ for runtimes_item_data in self.runtimes:
+ runtimes_item = runtimes_item_data.to_dict()
+ runtimes.append(runtimes_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "runtimes": runtimes,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.function_runtime_option import FunctionRuntimeOption
+ d = dict(src_dict)
+ runtimes = []
+ _runtimes = d.pop("runtimes")
+ for runtimes_item_data in (_runtimes):
+ runtimes_item = FunctionRuntimeOption.from_dict(runtimes_item_data)
+
+
+
+ runtimes.append(runtimes_item)
+
+
+ function_runtimes_response = cls(
+ runtimes=runtimes,
+ )
+
+
+ function_runtimes_response.additional_properties = d
+ return function_runtimes_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_scheduler.py b/src/volcano_sdk/_generated/models/function_scheduler.py
new file mode 100644
index 00000000..be5ce59c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_scheduler.py
@@ -0,0 +1,338 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.function_scheduler_schedule_kind import check_function_scheduler_schedule_kind
+from ..models.function_scheduler_schedule_kind import FunctionSchedulerScheduleKind
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.function_scheduler_payload import FunctionSchedulerPayload
+
+
+
+
+
+T = TypeVar("T", bound="FunctionScheduler")
+
+
+
+@_attrs_define
+class FunctionScheduler:
+ """
+ Attributes:
+ id (UUID | Unset):
+ project_id (UUID | Unset):
+ function_id (UUID | Unset):
+ name (str | Unset):
+ enabled (bool | Unset):
+ schedule_kind (FunctionSchedulerScheduleKind | Unset):
+ cron_expression (str | Unset):
+ payload (FunctionSchedulerPayload | Unset):
+ regions (list[str] | Unset):
+ regions_explicit (bool | Unset):
+ next_run_at (datetime.datetime | Unset):
+ last_started_at (datetime.datetime | Unset):
+ last_completed_at (datetime.datetime | Unset):
+ last_error (str | Unset):
+ run_count (int | Unset): Total number of times this scheduler has executed. 0 for a scheduler that has never
+ run.
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID | Unset = UNSET
+ project_id: UUID | Unset = UNSET
+ function_id: UUID | Unset = UNSET
+ name: str | Unset = UNSET
+ enabled: bool | Unset = UNSET
+ schedule_kind: FunctionSchedulerScheduleKind | Unset = UNSET
+ cron_expression: str | Unset = UNSET
+ payload: FunctionSchedulerPayload | Unset = UNSET
+ regions: list[str] | Unset = UNSET
+ regions_explicit: bool | Unset = UNSET
+ next_run_at: datetime.datetime | Unset = UNSET
+ last_started_at: datetime.datetime | Unset = UNSET
+ last_completed_at: datetime.datetime | Unset = UNSET
+ last_error: str | Unset = UNSET
+ run_count: int | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.function_scheduler_payload import FunctionSchedulerPayload
+ id: str | Unset = UNSET
+ if not isinstance(self.id, Unset):
+ id = str(self.id)
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ function_id: str | Unset = UNSET
+ if not isinstance(self.function_id, Unset):
+ function_id = str(self.function_id)
+
+ name = self.name
+
+ enabled = self.enabled
+
+ schedule_kind: str | Unset = UNSET
+ if not isinstance(self.schedule_kind, Unset):
+ schedule_kind = self.schedule_kind
+
+
+ cron_expression = self.cron_expression
+
+ payload: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.payload, Unset):
+ payload = self.payload.to_dict()
+
+ regions: list[str] | Unset = UNSET
+ if not isinstance(self.regions, Unset):
+ regions = self.regions
+
+
+
+ regions_explicit = self.regions_explicit
+
+ next_run_at: str | Unset = UNSET
+ if not isinstance(self.next_run_at, Unset):
+ next_run_at = self.next_run_at.isoformat()
+
+ last_started_at: str | Unset = UNSET
+ if not isinstance(self.last_started_at, Unset):
+ last_started_at = self.last_started_at.isoformat()
+
+ last_completed_at: str | Unset = UNSET
+ if not isinstance(self.last_completed_at, Unset):
+ last_completed_at = self.last_completed_at.isoformat()
+
+ last_error = self.last_error
+
+ run_count = self.run_count
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if id is not UNSET:
+ field_dict["id"] = id
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if function_id is not UNSET:
+ field_dict["function_id"] = function_id
+ if name is not UNSET:
+ field_dict["name"] = name
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if schedule_kind is not UNSET:
+ field_dict["schedule_kind"] = schedule_kind
+ if cron_expression is not UNSET:
+ field_dict["cron_expression"] = cron_expression
+ if payload is not UNSET:
+ field_dict["payload"] = payload
+ if regions is not UNSET:
+ field_dict["regions"] = regions
+ if regions_explicit is not UNSET:
+ field_dict["regions_explicit"] = regions_explicit
+ if next_run_at is not UNSET:
+ field_dict["next_run_at"] = next_run_at
+ if last_started_at is not UNSET:
+ field_dict["last_started_at"] = last_started_at
+ if last_completed_at is not UNSET:
+ field_dict["last_completed_at"] = last_completed_at
+ if last_error is not UNSET:
+ field_dict["last_error"] = last_error
+ if run_count is not UNSET:
+ field_dict["run_count"] = run_count
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.function_scheduler_payload import FunctionSchedulerPayload
+ d = dict(src_dict)
+ _id = d.pop("id", UNSET)
+ id: UUID | Unset
+ if isinstance(_id, Unset):
+ id = UNSET
+ else:
+ id = UUID(_id)
+
+
+
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ _function_id = d.pop("function_id", UNSET)
+ function_id: UUID | Unset
+ if isinstance(_function_id, Unset):
+ function_id = UNSET
+ else:
+ function_id = UUID(_function_id)
+
+
+
+
+ name = d.pop("name", UNSET)
+
+ enabled = d.pop("enabled", UNSET)
+
+ _schedule_kind = d.pop("schedule_kind", UNSET)
+ schedule_kind: FunctionSchedulerScheduleKind | Unset
+ if isinstance(_schedule_kind, Unset):
+ schedule_kind = UNSET
+ else:
+ schedule_kind = check_function_scheduler_schedule_kind(_schedule_kind)
+
+
+
+
+ cron_expression = d.pop("cron_expression", UNSET)
+
+ _payload = d.pop("payload", UNSET)
+ payload: FunctionSchedulerPayload | Unset
+ if isinstance(_payload, Unset):
+ payload = UNSET
+ else:
+ payload = FunctionSchedulerPayload.from_dict(_payload)
+
+
+
+
+ regions = cast(list[str], d.pop("regions", UNSET))
+
+
+ regions_explicit = d.pop("regions_explicit", UNSET)
+
+ _next_run_at = d.pop("next_run_at", UNSET)
+ next_run_at: datetime.datetime | Unset
+ if isinstance(_next_run_at, Unset):
+ next_run_at = UNSET
+ else:
+ next_run_at = datetime.datetime.fromisoformat(_next_run_at)
+
+
+
+
+ _last_started_at = d.pop("last_started_at", UNSET)
+ last_started_at: datetime.datetime | Unset
+ if isinstance(_last_started_at, Unset):
+ last_started_at = UNSET
+ else:
+ last_started_at = datetime.datetime.fromisoformat(_last_started_at)
+
+
+
+
+ _last_completed_at = d.pop("last_completed_at", UNSET)
+ last_completed_at: datetime.datetime | Unset
+ if isinstance(_last_completed_at, Unset):
+ last_completed_at = UNSET
+ else:
+ last_completed_at = datetime.datetime.fromisoformat(_last_completed_at)
+
+
+
+
+ last_error = d.pop("last_error", UNSET)
+
+ run_count = d.pop("run_count", UNSET)
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ function_scheduler = cls(
+ id=id,
+ project_id=project_id,
+ function_id=function_id,
+ name=name,
+ enabled=enabled,
+ schedule_kind=schedule_kind,
+ cron_expression=cron_expression,
+ payload=payload,
+ regions=regions,
+ regions_explicit=regions_explicit,
+ next_run_at=next_run_at,
+ last_started_at=last_started_at,
+ last_completed_at=last_completed_at,
+ last_error=last_error,
+ run_count=run_count,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ function_scheduler.additional_properties = d
+ return function_scheduler
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_scheduler_list_response.py b/src/volcano_sdk/_generated/models/function_scheduler_list_response.py
new file mode 100644
index 00000000..d9ca304c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_scheduler_list_response.py
@@ -0,0 +1,146 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.function_scheduler import FunctionScheduler
+
+
+
+
+
+T = TypeVar("T", bound="FunctionSchedulerListResponse")
+
+
+
+@_attrs_define
+class FunctionSchedulerListResponse:
+ """
+ Attributes:
+ data (list[FunctionScheduler]):
+ page (int):
+ limit (int):
+ total (int):
+ has_more (bool):
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ """
+
+ data: list[FunctionScheduler]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.function_scheduler import FunctionScheduler
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.function_scheduler import FunctionScheduler
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = FunctionScheduler.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ function_scheduler_list_response = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ function_scheduler_list_response.additional_properties = d
+ return function_scheduler_list_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_scheduler_payload.py b/src/volcano_sdk/_generated/models/function_scheduler_payload.py
new file mode 100644
index 00000000..6e7c52f5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_scheduler_payload.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="FunctionSchedulerPayload")
+
+
+
+@_attrs_define
+class FunctionSchedulerPayload:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ function_scheduler_payload = cls(
+ )
+
+
+ function_scheduler_payload.additional_properties = d
+ return function_scheduler_payload
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/function_scheduler_schedule_kind.py b/src/volcano_sdk/_generated/models/function_scheduler_schedule_kind.py
new file mode 100644
index 00000000..18aac46e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_scheduler_schedule_kind.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FunctionSchedulerScheduleKind = Literal['cron']
+
+FUNCTION_SCHEDULER_SCHEDULE_KIND_VALUES: set[FunctionSchedulerScheduleKind] = { 'cron', }
+
+def check_function_scheduler_schedule_kind(value: str) -> FunctionSchedulerScheduleKind:
+ if value in FUNCTION_SCHEDULER_SCHEDULE_KIND_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FUNCTION_SCHEDULER_SCHEDULE_KIND_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/function_status.py b/src/volcano_sdk/_generated/models/function_status.py
new file mode 100644
index 00000000..8061efe2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/function_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+FunctionStatus = Literal['active', 'deleting', 'failed', 'provisioning']
+
+FUNCTION_STATUS_VALUES: set[FunctionStatus] = { 'active', 'deleting', 'failed', 'provisioning', }
+
+def check_function_status(value: str) -> FunctionStatus:
+ if value in FUNCTION_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {FUNCTION_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/get_auth_methods_response_200.py b/src/volcano_sdk/_generated/models/get_auth_methods_response_200.py
new file mode 100644
index 00000000..109a58c9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_auth_methods_response_200.py
@@ -0,0 +1,158 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.get_auth_methods_response_200_anonymous import GetAuthMethodsResponse200Anonymous
+ from ..models.get_auth_methods_response_200_email_password import GetAuthMethodsResponse200EmailPassword
+ from ..models.get_auth_methods_response_200_oauth_providers_item import GetAuthMethodsResponse200OauthProvidersItem
+
+
+
+
+
+T = TypeVar("T", bound="GetAuthMethodsResponse200")
+
+
+
+@_attrs_define
+class GetAuthMethodsResponse200:
+ """
+ Attributes:
+ email_password (GetAuthMethodsResponse200EmailPassword | Unset):
+ anonymous (GetAuthMethodsResponse200Anonymous | Unset):
+ oauth_providers (list[GetAuthMethodsResponse200OauthProvidersItem] | Unset):
+ available_methods (list[str] | Unset): Example: ['email_password', 'oauth_google', 'oauth_github'].
+ """
+
+ email_password: GetAuthMethodsResponse200EmailPassword | Unset = UNSET
+ anonymous: GetAuthMethodsResponse200Anonymous | Unset = UNSET
+ oauth_providers: list[GetAuthMethodsResponse200OauthProvidersItem] | Unset = UNSET
+ available_methods: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.get_auth_methods_response_200_anonymous import GetAuthMethodsResponse200Anonymous
+ from ..models.get_auth_methods_response_200_email_password import GetAuthMethodsResponse200EmailPassword
+ from ..models.get_auth_methods_response_200_oauth_providers_item import GetAuthMethodsResponse200OauthProvidersItem
+ email_password: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.email_password, Unset):
+ email_password = self.email_password.to_dict()
+
+ anonymous: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.anonymous, Unset):
+ anonymous = self.anonymous.to_dict()
+
+ oauth_providers: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.oauth_providers, Unset):
+ oauth_providers = []
+ for oauth_providers_item_data in self.oauth_providers:
+ oauth_providers_item = oauth_providers_item_data.to_dict()
+ oauth_providers.append(oauth_providers_item)
+
+
+
+ available_methods: list[str] | Unset = UNSET
+ if not isinstance(self.available_methods, Unset):
+ available_methods = self.available_methods
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if email_password is not UNSET:
+ field_dict["email_password"] = email_password
+ if anonymous is not UNSET:
+ field_dict["anonymous"] = anonymous
+ if oauth_providers is not UNSET:
+ field_dict["oauth_providers"] = oauth_providers
+ if available_methods is not UNSET:
+ field_dict["available_methods"] = available_methods
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.get_auth_methods_response_200_anonymous import GetAuthMethodsResponse200Anonymous
+ from ..models.get_auth_methods_response_200_email_password import GetAuthMethodsResponse200EmailPassword
+ from ..models.get_auth_methods_response_200_oauth_providers_item import GetAuthMethodsResponse200OauthProvidersItem
+ d = dict(src_dict)
+ _email_password = d.pop("email_password", UNSET)
+ email_password: GetAuthMethodsResponse200EmailPassword | Unset
+ if isinstance(_email_password, Unset):
+ email_password = UNSET
+ else:
+ email_password = GetAuthMethodsResponse200EmailPassword.from_dict(_email_password)
+
+
+
+
+ _anonymous = d.pop("anonymous", UNSET)
+ anonymous: GetAuthMethodsResponse200Anonymous | Unset
+ if isinstance(_anonymous, Unset):
+ anonymous = UNSET
+ else:
+ anonymous = GetAuthMethodsResponse200Anonymous.from_dict(_anonymous)
+
+
+
+
+ _oauth_providers = d.pop("oauth_providers", UNSET)
+ oauth_providers: list[GetAuthMethodsResponse200OauthProvidersItem] | Unset = UNSET
+ if _oauth_providers is not UNSET:
+ oauth_providers = []
+ for oauth_providers_item_data in _oauth_providers:
+ oauth_providers_item = GetAuthMethodsResponse200OauthProvidersItem.from_dict(oauth_providers_item_data)
+
+
+
+ oauth_providers.append(oauth_providers_item)
+
+
+ available_methods = cast(list[str], d.pop("available_methods", UNSET))
+
+
+ get_auth_methods_response_200 = cls(
+ email_password=email_password,
+ anonymous=anonymous,
+ oauth_providers=oauth_providers,
+ available_methods=available_methods,
+ )
+
+
+ get_auth_methods_response_200.additional_properties = d
+ return get_auth_methods_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/get_auth_methods_response_200_anonymous.py b/src/volcano_sdk/_generated/models/get_auth_methods_response_200_anonymous.py
new file mode 100644
index 00000000..380f758a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_auth_methods_response_200_anonymous.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="GetAuthMethodsResponse200Anonymous")
+
+
+
+@_attrs_define
+class GetAuthMethodsResponse200Anonymous:
+ """
+ Attributes:
+ enabled (bool | Unset):
+ method (str | Unset):
+ name (str | Unset):
+ """
+
+ enabled: bool | Unset = UNSET
+ method: str | Unset = UNSET
+ name: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enabled = self.enabled
+
+ method = self.method
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if method is not UNSET:
+ field_dict["method"] = method
+ if name is not UNSET:
+ field_dict["name"] = name
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ method = d.pop("method", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ get_auth_methods_response_200_anonymous = cls(
+ enabled=enabled,
+ method=method,
+ name=name,
+ )
+
+
+ get_auth_methods_response_200_anonymous.additional_properties = d
+ return get_auth_methods_response_200_anonymous
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/get_auth_methods_response_200_email_password.py b/src/volcano_sdk/_generated/models/get_auth_methods_response_200_email_password.py
new file mode 100644
index 00000000..67f6e229
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_auth_methods_response_200_email_password.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="GetAuthMethodsResponse200EmailPassword")
+
+
+
+@_attrs_define
+class GetAuthMethodsResponse200EmailPassword:
+ """
+ Attributes:
+ enabled (bool | Unset):
+ method (str | Unset):
+ name (str | Unset):
+ """
+
+ enabled: bool | Unset = UNSET
+ method: str | Unset = UNSET
+ name: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enabled = self.enabled
+
+ method = self.method
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if method is not UNSET:
+ field_dict["method"] = method
+ if name is not UNSET:
+ field_dict["name"] = name
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ method = d.pop("method", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ get_auth_methods_response_200_email_password = cls(
+ enabled=enabled,
+ method=method,
+ name=name,
+ )
+
+
+ get_auth_methods_response_200_email_password.additional_properties = d
+ return get_auth_methods_response_200_email_password
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/get_auth_methods_response_200_oauth_providers_item.py b/src/volcano_sdk/_generated/models/get_auth_methods_response_200_oauth_providers_item.py
new file mode 100644
index 00000000..85aeee01
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_auth_methods_response_200_oauth_providers_item.py
@@ -0,0 +1,129 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="GetAuthMethodsResponse200OauthProvidersItem")
+
+
+
+@_attrs_define
+class GetAuthMethodsResponse200OauthProvidersItem:
+ """
+ Attributes:
+ enabled (bool | Unset):
+ method (str | Unset):
+ provider (str | Unset):
+ name (str | Unset):
+ redirect_url (str | Unset):
+ scopes (list[str] | Unset):
+ """
+
+ enabled: bool | Unset = UNSET
+ method: str | Unset = UNSET
+ provider: str | Unset = UNSET
+ name: str | Unset = UNSET
+ redirect_url: str | Unset = UNSET
+ scopes: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enabled = self.enabled
+
+ method = self.method
+
+ provider = self.provider
+
+ name = self.name
+
+ redirect_url = self.redirect_url
+
+ scopes: list[str] | Unset = UNSET
+ if not isinstance(self.scopes, Unset):
+ scopes = self.scopes
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if method is not UNSET:
+ field_dict["method"] = method
+ if provider is not UNSET:
+ field_dict["provider"] = provider
+ if name is not UNSET:
+ field_dict["name"] = name
+ if redirect_url is not UNSET:
+ field_dict["redirect_url"] = redirect_url
+ if scopes is not UNSET:
+ field_dict["scopes"] = scopes
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ method = d.pop("method", UNSET)
+
+ provider = d.pop("provider", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ redirect_url = d.pop("redirect_url", UNSET)
+
+ scopes = cast(list[str], d.pop("scopes", UNSET))
+
+
+ get_auth_methods_response_200_oauth_providers_item = cls(
+ enabled=enabled,
+ method=method,
+ provider=provider,
+ name=name,
+ redirect_url=redirect_url,
+ scopes=scopes,
+ )
+
+
+ get_auth_methods_response_200_oauth_providers_item.additional_properties = d
+ return get_auth_methods_response_200_oauth_providers_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/get_database_stats_granularity.py b/src/volcano_sdk/_generated/models/get_database_stats_granularity.py
new file mode 100644
index 00000000..73ed08ec
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_database_stats_granularity.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+GetDatabaseStatsGranularity = Literal['daily', 'hourly', 'monthly']
+
+GET_DATABASE_STATS_GRANULARITY_VALUES: set[GetDatabaseStatsGranularity] = { 'daily', 'hourly', 'monthly', }
+
+def check_get_database_stats_granularity(value: str) -> GetDatabaseStatsGranularity:
+ if value in GET_DATABASE_STATS_GRANULARITY_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {GET_DATABASE_STATS_GRANULARITY_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/get_default_email_template_type.py b/src/volcano_sdk/_generated/models/get_default_email_template_type.py
new file mode 100644
index 00000000..ac0a2f32
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_default_email_template_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+GetDefaultEmailTemplateType = Literal['confirmation', 'password_changed', 'password_reset', 'welcome']
+
+GET_DEFAULT_EMAIL_TEMPLATE_TYPE_VALUES: set[GetDefaultEmailTemplateType] = { 'confirmation', 'password_changed', 'password_reset', 'welcome', }
+
+def check_get_default_email_template_type(value: str) -> GetDefaultEmailTemplateType:
+ if value in GET_DEFAULT_EMAIL_TEMPLATE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {GET_DEFAULT_EMAIL_TEMPLATE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/get_default_email_templates_response_200.py b/src/volcano_sdk/_generated/models/get_default_email_templates_response_200.py
new file mode 100644
index 00000000..4827dbc9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_default_email_templates_response_200.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.email_template import EmailTemplate
+
+
+
+
+
+T = TypeVar("T", bound="GetDefaultEmailTemplatesResponse200")
+
+
+
+@_attrs_define
+class GetDefaultEmailTemplatesResponse200:
+ """
+ Attributes:
+ data (list[EmailTemplate] | Unset):
+ """
+
+ data: list[EmailTemplate] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.email_template import EmailTemplate
+ data: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.data, Unset):
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if data is not UNSET:
+ field_dict["data"] = data
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.email_template import EmailTemplate
+ d = dict(src_dict)
+ _data = d.pop("data", UNSET)
+ data: list[EmailTemplate] | Unset = UNSET
+ if _data is not UNSET:
+ data = []
+ for data_item_data in _data:
+ data_item = EmailTemplate.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ get_default_email_templates_response_200 = cls(
+ data=data,
+ )
+
+
+ get_default_email_templates_response_200.additional_properties = d
+ return get_default_email_templates_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/get_email_template_type.py b/src/volcano_sdk/_generated/models/get_email_template_type.py
new file mode 100644
index 00000000..a9f05643
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_email_template_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+GetEmailTemplateType = Literal['confirmation', 'password_changed', 'password_reset', 'welcome']
+
+GET_EMAIL_TEMPLATE_TYPE_VALUES: set[GetEmailTemplateType] = { 'confirmation', 'password_changed', 'password_reset', 'welcome', }
+
+def check_get_email_template_type(value: str) -> GetEmailTemplateType:
+ if value in GET_EMAIL_TEMPLATE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {GET_EMAIL_TEMPLATE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/get_o_auth_config_provider.py b/src/volcano_sdk/_generated/models/get_o_auth_config_provider.py
new file mode 100644
index 00000000..408b82c6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_o_auth_config_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+GetOAuthConfigProvider = Literal['apple', 'device', 'github', 'google', 'microsoft']
+
+GET_O_AUTH_CONFIG_PROVIDER_VALUES: set[GetOAuthConfigProvider] = { 'apple', 'device', 'github', 'google', 'microsoft', }
+
+def check_get_o_auth_config_provider(value: str) -> GetOAuthConfigProvider:
+ if value in GET_O_AUTH_CONFIG_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {GET_O_AUTH_CONFIG_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/get_o_auth_provider_token_provider.py b/src/volcano_sdk/_generated/models/get_o_auth_provider_token_provider.py
new file mode 100644
index 00000000..e4f24da8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_o_auth_provider_token_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+GetOAuthProviderTokenProvider = Literal['apple', 'github', 'google', 'microsoft']
+
+GET_O_AUTH_PROVIDER_TOKEN_PROVIDER_VALUES: set[GetOAuthProviderTokenProvider] = { 'apple', 'github', 'google', 'microsoft', }
+
+def check_get_o_auth_provider_token_provider(value: str) -> GetOAuthProviderTokenProvider:
+ if value in GET_O_AUTH_PROVIDER_TOKEN_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {GET_O_AUTH_PROVIDER_TOKEN_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/get_o_auth_provider_token_response_200.py b/src/volcano_sdk/_generated/models/get_o_auth_provider_token_response_200.py
new file mode 100644
index 00000000..2cb11abb
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_o_auth_provider_token_response_200.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="GetOAuthProviderTokenResponse200")
+
+
+
+@_attrs_define
+class GetOAuthProviderTokenResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ provider (str | Unset):
+ expires_in (int | Unset):
+ """
+
+ message: str | Unset = UNSET
+ provider: str | Unset = UNSET
+ expires_in: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+ provider = self.provider
+
+ expires_in = self.expires_in
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+ if provider is not UNSET:
+ field_dict["provider"] = provider
+ if expires_in is not UNSET:
+ field_dict["expires_in"] = expires_in
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ provider = d.pop("provider", UNSET)
+
+ expires_in = d.pop("expires_in", UNSET)
+
+ get_o_auth_provider_token_response_200 = cls(
+ message=message,
+ provider=provider,
+ expires_in=expires_in,
+ )
+
+
+ get_o_auth_provider_token_response_200.additional_properties = d
+ return get_o_auth_provider_token_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/get_project_config_format.py b/src/volcano_sdk/_generated/models/get_project_config_format.py
new file mode 100644
index 00000000..630aadbc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/get_project_config_format.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+GetProjectConfigFormat = Literal['json', 'yaml']
+
+GET_PROJECT_CONFIG_FORMAT_VALUES: set[GetProjectConfigFormat] = { 'json', 'yaml', }
+
+def check_get_project_config_format(value: str) -> GetProjectConfigFormat:
+ if value in GET_PROJECT_CONFIG_FORMAT_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {GET_PROJECT_CONFIG_FORMAT_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/git_connect_start_response.py b/src/volcano_sdk/_generated/models/git_connect_start_response.py
new file mode 100644
index 00000000..b91b770d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/git_connect_start_response.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="GitConnectStartResponse")
+
+
+
+@_attrs_define
+class GitConnectStartResponse:
+ """
+ Attributes:
+ authorization_url (str):
+ """
+
+ authorization_url: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ authorization_url = self.authorization_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "authorization_url": authorization_url,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ authorization_url = d.pop("authorization_url")
+
+ git_connect_start_response = cls(
+ authorization_url=authorization_url,
+ )
+
+
+ git_connect_start_response.additional_properties = d
+ return git_connect_start_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/git_connection.py b/src/volcano_sdk/_generated/models/git_connection.py
new file mode 100644
index 00000000..14a36848
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/git_connection.py
@@ -0,0 +1,147 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="GitConnection")
+
+
+
+@_attrs_define
+class GitConnection:
+ """
+ Attributes:
+ id (UUID):
+ provider (str):
+ provider_user_id (str):
+ provider_login (str):
+ status (str):
+ last_authenticated_at (datetime.datetime):
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ """
+
+ id: UUID
+ provider: str
+ provider_user_id: str
+ provider_login: str
+ status: str
+ last_authenticated_at: datetime.datetime
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ provider = self.provider
+
+ provider_user_id = self.provider_user_id
+
+ provider_login = self.provider_login
+
+ status = self.status
+
+ last_authenticated_at = self.last_authenticated_at.isoformat()
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "provider": provider,
+ "provider_user_id": provider_user_id,
+ "provider_login": provider_login,
+ "status": status,
+ "last_authenticated_at": last_authenticated_at,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ provider = d.pop("provider")
+
+ provider_user_id = d.pop("provider_user_id")
+
+ provider_login = d.pop("provider_login")
+
+ status = d.pop("status")
+
+ last_authenticated_at = datetime.datetime.fromisoformat(d.pop("last_authenticated_at"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ git_connection = cls(
+ id=id,
+ provider=provider,
+ provider_user_id=provider_user_id,
+ provider_login=provider_login,
+ status=status,
+ last_authenticated_at=last_authenticated_at,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ git_connection.additional_properties = d
+ return git_connection
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/git_connections_response.py b/src/volcano_sdk/_generated/models/git_connections_response.py
new file mode 100644
index 00000000..4d3d9f81
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/git_connections_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.git_connection import GitConnection
+
+
+
+
+
+T = TypeVar("T", bound="GitConnectionsResponse")
+
+
+
+@_attrs_define
+class GitConnectionsResponse:
+ """
+ Attributes:
+ connections (list[GitConnection]):
+ """
+
+ connections: list[GitConnection]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.git_connection import GitConnection
+ connections = []
+ for connections_item_data in self.connections:
+ connections_item = connections_item_data.to_dict()
+ connections.append(connections_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "connections": connections,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.git_connection import GitConnection
+ d = dict(src_dict)
+ connections = []
+ _connections = d.pop("connections")
+ for connections_item_data in (_connections):
+ connections_item = GitConnection.from_dict(connections_item_data)
+
+
+
+ connections.append(connections_item)
+
+
+ git_connections_response = cls(
+ connections=connections,
+ )
+
+
+ git_connections_response.additional_properties = d
+ return git_connections_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/git_installation.py b/src/volcano_sdk/_generated/models/git_installation.py
new file mode 100644
index 00000000..177fdd5d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/git_installation.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="GitInstallation")
+
+
+
+@_attrs_define
+class GitInstallation:
+ """
+ Attributes:
+ id (int):
+ account_login (str):
+ account_type (str):
+ repository_selection (str):
+ """
+
+ id: int
+ account_login: str
+ account_type: str
+ repository_selection: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = self.id
+
+ account_login = self.account_login
+
+ account_type = self.account_type
+
+ repository_selection = self.repository_selection
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "account_login": account_login,
+ "account_type": account_type,
+ "repository_selection": repository_selection,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = d.pop("id")
+
+ account_login = d.pop("account_login")
+
+ account_type = d.pop("account_type")
+
+ repository_selection = d.pop("repository_selection")
+
+ git_installation = cls(
+ id=id,
+ account_login=account_login,
+ account_type=account_type,
+ repository_selection=repository_selection,
+ )
+
+
+ git_installation.additional_properties = d
+ return git_installation
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/git_installations_response.py b/src/volcano_sdk/_generated/models/git_installations_response.py
new file mode 100644
index 00000000..87640c4a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/git_installations_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.git_installation import GitInstallation
+
+
+
+
+
+T = TypeVar("T", bound="GitInstallationsResponse")
+
+
+
+@_attrs_define
+class GitInstallationsResponse:
+ """
+ Attributes:
+ installations (list[GitInstallation]):
+ """
+
+ installations: list[GitInstallation]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.git_installation import GitInstallation
+ installations = []
+ for installations_item_data in self.installations:
+ installations_item = installations_item_data.to_dict()
+ installations.append(installations_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "installations": installations,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.git_installation import GitInstallation
+ d = dict(src_dict)
+ installations = []
+ _installations = d.pop("installations")
+ for installations_item_data in (_installations):
+ installations_item = GitInstallation.from_dict(installations_item_data)
+
+
+
+ installations.append(installations_item)
+
+
+ git_installations_response = cls(
+ installations=installations,
+ )
+
+
+ git_installations_response.additional_properties = d
+ return git_installations_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/git_repositories_response.py b/src/volcano_sdk/_generated/models/git_repositories_response.py
new file mode 100644
index 00000000..57d71734
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/git_repositories_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.git_repository import GitRepository
+
+
+
+
+
+T = TypeVar("T", bound="GitRepositoriesResponse")
+
+
+
+@_attrs_define
+class GitRepositoriesResponse:
+ """
+ Attributes:
+ repositories (list[GitRepository]):
+ """
+
+ repositories: list[GitRepository]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.git_repository import GitRepository
+ repositories = []
+ for repositories_item_data in self.repositories:
+ repositories_item = repositories_item_data.to_dict()
+ repositories.append(repositories_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "repositories": repositories,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.git_repository import GitRepository
+ d = dict(src_dict)
+ repositories = []
+ _repositories = d.pop("repositories")
+ for repositories_item_data in (_repositories):
+ repositories_item = GitRepository.from_dict(repositories_item_data)
+
+
+
+ repositories.append(repositories_item)
+
+
+ git_repositories_response = cls(
+ repositories=repositories,
+ )
+
+
+ git_repositories_response.additional_properties = d
+ return git_repositories_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/git_repository.py b/src/volcano_sdk/_generated/models/git_repository.py
new file mode 100644
index 00000000..c191bfd8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/git_repository.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="GitRepository")
+
+
+
+@_attrs_define
+class GitRepository:
+ """
+ Attributes:
+ id (int): Stable GitHub repository id (repository.id), unchanged by renames.
+ full_name (str):
+ default_branch (str):
+ private (bool):
+ """
+
+ id: int
+ full_name: str
+ default_branch: str
+ private: bool
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = self.id
+
+ full_name = self.full_name
+
+ default_branch = self.default_branch
+
+ private = self.private
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "full_name": full_name,
+ "default_branch": default_branch,
+ "private": private,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = d.pop("id")
+
+ full_name = d.pop("full_name")
+
+ default_branch = d.pop("default_branch")
+
+ private = d.pop("private")
+
+ git_repository = cls(
+ id=id,
+ full_name=full_name,
+ default_branch=default_branch,
+ private=private,
+ )
+
+
+ git_repository.additional_properties = d
+ return git_repository
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/hosted_auth_page_type.py b/src/volcano_sdk/_generated/models/hosted_auth_page_type.py
new file mode 100644
index 00000000..337332c5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/hosted_auth_page_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+HostedAuthPageType = Literal['login', 'reset-password']
+
+HOSTED_AUTH_PAGE_TYPE_VALUES: set[HostedAuthPageType] = { 'login', 'reset-password', }
+
+def check_hosted_auth_page_type(value: str) -> HostedAuthPageType:
+ if value in HOSTED_AUTH_PAGE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {HOSTED_AUTH_PAGE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/hosted_login_email_check_request.py b/src/volcano_sdk/_generated/models/hosted_login_email_check_request.py
new file mode 100644
index 00000000..1c6183e1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/hosted_login_email_check_request.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="HostedLoginEmailCheckRequest")
+
+
+
+@_attrs_define
+class HostedLoginEmailCheckRequest:
+ """
+ Attributes:
+ email (str):
+ """
+
+ email: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ email = self.email
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "email": email,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ email = d.pop("email")
+
+ hosted_login_email_check_request = cls(
+ email=email,
+ )
+
+
+ hosted_login_email_check_request.additional_properties = d
+ return hosted_login_email_check_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/hosted_login_email_check_response.py b/src/volcano_sdk/_generated/models/hosted_login_email_check_response.py
new file mode 100644
index 00000000..7efb410b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/hosted_login_email_check_response.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="HostedLoginEmailCheckResponse")
+
+
+
+@_attrs_define
+class HostedLoginEmailCheckResponse:
+ """
+ Attributes:
+ exists (bool | Unset):
+ """
+
+ exists: bool | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ exists = self.exists
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if exists is not UNSET:
+ field_dict["exists"] = exists
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ exists = d.pop("exists", UNSET)
+
+ hosted_login_email_check_response = cls(
+ exists=exists,
+ )
+
+
+ hosted_login_email_check_response.additional_properties = d
+ return hosted_login_email_check_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/hosted_login_options_response.py b/src/volcano_sdk/_generated/models/hosted_login_options_response.py
new file mode 100644
index 00000000..745f2831
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/hosted_login_options_response.py
@@ -0,0 +1,120 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="HostedLoginOptionsResponse")
+
+
+
+@_attrs_define
+class HostedLoginOptionsResponse:
+ """
+ Attributes:
+ require_email_confirmation (bool | Unset):
+ email_password_enabled (bool | Unset):
+ enable_signup (bool | Unset):
+ post_auth_redirect_url (str | Unset):
+ oauth_providers (list[str] | Unset):
+ """
+
+ require_email_confirmation: bool | Unset = UNSET
+ email_password_enabled: bool | Unset = UNSET
+ enable_signup: bool | Unset = UNSET
+ post_auth_redirect_url: str | Unset = UNSET
+ oauth_providers: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ require_email_confirmation = self.require_email_confirmation
+
+ email_password_enabled = self.email_password_enabled
+
+ enable_signup = self.enable_signup
+
+ post_auth_redirect_url = self.post_auth_redirect_url
+
+ oauth_providers: list[str] | Unset = UNSET
+ if not isinstance(self.oauth_providers, Unset):
+ oauth_providers = self.oauth_providers
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if require_email_confirmation is not UNSET:
+ field_dict["require_email_confirmation"] = require_email_confirmation
+ if email_password_enabled is not UNSET:
+ field_dict["email_password_enabled"] = email_password_enabled
+ if enable_signup is not UNSET:
+ field_dict["enable_signup"] = enable_signup
+ if post_auth_redirect_url is not UNSET:
+ field_dict["post_auth_redirect_url"] = post_auth_redirect_url
+ if oauth_providers is not UNSET:
+ field_dict["oauth_providers"] = oauth_providers
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ require_email_confirmation = d.pop("require_email_confirmation", UNSET)
+
+ email_password_enabled = d.pop("email_password_enabled", UNSET)
+
+ enable_signup = d.pop("enable_signup", UNSET)
+
+ post_auth_redirect_url = d.pop("post_auth_redirect_url", UNSET)
+
+ oauth_providers = cast(list[str], d.pop("oauth_providers", UNSET))
+
+
+ hosted_login_options_response = cls(
+ require_email_confirmation=require_email_confirmation,
+ email_password_enabled=email_password_enabled,
+ enable_signup=enable_signup,
+ post_auth_redirect_url=post_auth_redirect_url,
+ oauth_providers=oauth_providers,
+ )
+
+
+ hosted_login_options_response.additional_properties = d
+ return hosted_login_options_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/hosted_renderable_page_type.py b/src/volcano_sdk/_generated/models/hosted_renderable_page_type.py
new file mode 100644
index 00000000..71398979
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/hosted_renderable_page_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+HostedRenderablePageType = Literal['reset-password']
+
+HOSTED_RENDERABLE_PAGE_TYPE_VALUES: set[HostedRenderablePageType] = { 'reset-password', }
+
+def check_hosted_renderable_page_type(value: str) -> HostedRenderablePageType:
+ if value in HOSTED_RENDERABLE_PAGE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {HOSTED_RENDERABLE_PAGE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/import_connect_start_response.py b/src/volcano_sdk/_generated/models/import_connect_start_response.py
new file mode 100644
index 00000000..d9e82eef
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/import_connect_start_response.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ImportConnectStartResponse")
+
+
+
+@_attrs_define
+class ImportConnectStartResponse:
+ """
+ Attributes:
+ authorization_url (str):
+ """
+
+ authorization_url: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ authorization_url = self.authorization_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "authorization_url": authorization_url,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ authorization_url = d.pop("authorization_url")
+
+ import_connect_start_response = cls(
+ authorization_url=authorization_url,
+ )
+
+
+ import_connect_start_response.additional_properties = d
+ return import_connect_start_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/import_connection.py b/src/volcano_sdk/_generated/models/import_connection.py
new file mode 100644
index 00000000..40e43341
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/import_connection.py
@@ -0,0 +1,205 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.import_provider import check_import_provider
+from ..models.import_provider import ImportProvider
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="ImportConnection")
+
+
+
+@_attrs_define
+class ImportConnection:
+ """
+ Attributes:
+ id (UUID):
+ provider (ImportProvider):
+ account_id (str):
+ account_name (str):
+ configuration_id (str):
+ granted_scopes (list[str]):
+ status (str):
+ last_authenticated_at (datetime.datetime):
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ expires_at (datetime.datetime | None | Unset):
+ """
+
+ id: UUID
+ provider: ImportProvider
+ account_id: str
+ account_name: str
+ configuration_id: str
+ granted_scopes: list[str]
+ status: str
+ last_authenticated_at: datetime.datetime
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ expires_at: datetime.datetime | None | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ provider: str = self.provider
+
+ account_id = self.account_id
+
+ account_name = self.account_name
+
+ configuration_id = self.configuration_id
+
+ granted_scopes = self.granted_scopes
+
+
+
+ status = self.status
+
+ last_authenticated_at = self.last_authenticated_at.isoformat()
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ expires_at: None | str | Unset
+ if isinstance(self.expires_at, Unset):
+ expires_at = UNSET
+ elif isinstance(self.expires_at, datetime.datetime):
+ expires_at = self.expires_at.isoformat()
+ else:
+ expires_at = self.expires_at
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "provider": provider,
+ "account_id": account_id,
+ "account_name": account_name,
+ "configuration_id": configuration_id,
+ "granted_scopes": granted_scopes,
+ "status": status,
+ "last_authenticated_at": last_authenticated_at,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if expires_at is not UNSET:
+ field_dict["expires_at"] = expires_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ provider = check_import_provider(d.pop("provider"))
+
+
+
+
+ account_id = d.pop("account_id")
+
+ account_name = d.pop("account_name")
+
+ configuration_id = d.pop("configuration_id")
+
+ granted_scopes = cast(list[str], d.pop("granted_scopes"))
+
+
+ status = d.pop("status")
+
+ last_authenticated_at = datetime.datetime.fromisoformat(d.pop("last_authenticated_at"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ def _parse_expires_at(data: object) -> datetime.datetime | None | Unset:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ try:
+ if not isinstance(data, str):
+ raise TypeError()
+ expires_at_type_0 = datetime.datetime.fromisoformat(data)
+
+
+
+ return expires_at_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(datetime.datetime | None | Unset, data)
+
+ expires_at = _parse_expires_at(d.pop("expires_at", UNSET))
+
+
+ import_connection = cls(
+ id=id,
+ provider=provider,
+ account_id=account_id,
+ account_name=account_name,
+ configuration_id=configuration_id,
+ granted_scopes=granted_scopes,
+ status=status,
+ last_authenticated_at=last_authenticated_at,
+ created_at=created_at,
+ updated_at=updated_at,
+ expires_at=expires_at,
+ )
+
+
+ import_connection.additional_properties = d
+ return import_connection
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/import_connections_response.py b/src/volcano_sdk/_generated/models/import_connections_response.py
new file mode 100644
index 00000000..f6101beb
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/import_connections_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.import_connection import ImportConnection
+
+
+
+
+
+T = TypeVar("T", bound="ImportConnectionsResponse")
+
+
+
+@_attrs_define
+class ImportConnectionsResponse:
+ """
+ Attributes:
+ connections (list[ImportConnection]):
+ """
+
+ connections: list[ImportConnection]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.import_connection import ImportConnection
+ connections = []
+ for connections_item_data in self.connections:
+ connections_item = connections_item_data.to_dict()
+ connections.append(connections_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "connections": connections,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.import_connection import ImportConnection
+ d = dict(src_dict)
+ connections = []
+ _connections = d.pop("connections")
+ for connections_item_data in (_connections):
+ connections_item = ImportConnection.from_dict(connections_item_data)
+
+
+
+ connections.append(connections_item)
+
+
+ import_connections_response = cls(
+ connections=connections,
+ )
+
+
+ import_connections_response.additional_properties = d
+ return import_connections_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/import_provider.py b/src/volcano_sdk/_generated/models/import_provider.py
new file mode 100644
index 00000000..92fc3553
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/import_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ImportProvider = Literal['vercel']
+
+IMPORT_PROVIDER_VALUES: set[ImportProvider] = { 'vercel', }
+
+def check_import_provider(value: str) -> ImportProvider:
+ if value in IMPORT_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {IMPORT_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/import_source.py b/src/volcano_sdk/_generated/models/import_source.py
new file mode 100644
index 00000000..959c8c79
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/import_source.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ImportSource")
+
+
+
+@_attrs_define
+class ImportSource:
+ """
+ Attributes:
+ id (str):
+ name (str):
+ account_id (str):
+ framework (str):
+ """
+
+ id: str
+ name: str
+ account_id: str
+ framework: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = self.id
+
+ name = self.name
+
+ account_id = self.account_id
+
+ framework = self.framework
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ "account_id": account_id,
+ "framework": framework,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = d.pop("id")
+
+ name = d.pop("name")
+
+ account_id = d.pop("account_id")
+
+ framework = d.pop("framework")
+
+ import_source = cls(
+ id=id,
+ name=name,
+ account_id=account_id,
+ framework=framework,
+ )
+
+
+ import_source.additional_properties = d
+ return import_source
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/import_sources_response.py b/src/volcano_sdk/_generated/models/import_sources_response.py
new file mode 100644
index 00000000..8f4cbd98
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/import_sources_response.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.import_source import ImportSource
+
+
+
+
+
+T = TypeVar("T", bound="ImportSourcesResponse")
+
+
+
+@_attrs_define
+class ImportSourcesResponse:
+ """
+ Attributes:
+ sources (list[ImportSource]):
+ """
+
+ sources: list[ImportSource]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.import_source import ImportSource
+ sources = []
+ for sources_item_data in self.sources:
+ sources_item = sources_item_data.to_dict()
+ sources.append(sources_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "sources": sources,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.import_source import ImportSource
+ d = dict(src_dict)
+ sources = []
+ _sources = d.pop("sources")
+ for sources_item_data in (_sources):
+ sources_item = ImportSource.from_dict(sources_item_data)
+
+
+
+ sources.append(sources_item)
+
+
+ import_sources_response = cls(
+ sources=sources,
+ )
+
+
+ import_sources_response.additional_properties = d
+ return import_sources_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_anon_keys_response_200.py b/src/volcano_sdk/_generated/models/list_anon_keys_response_200.py
new file mode 100644
index 00000000..edafb363
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_anon_keys_response_200.py
@@ -0,0 +1,137 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.anon_key import AnonKey
+
+
+
+
+
+T = TypeVar("T", bound="ListAnonKeysResponse200")
+
+
+
+@_attrs_define
+class ListAnonKeysResponse200:
+ """
+ Attributes:
+ data (list[AnonKey] | Unset):
+ total (int | Unset): Total number of items matching the query (so the UI can render numbered pages).
+ has_more (bool | Unset): Whether a next page exists.
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only). Send as
+ `ending_before`.
+ """
+
+ data: list[AnonKey] | Unset = UNSET
+ total: int | Unset = UNSET
+ has_more: bool | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.anon_key import AnonKey
+ data: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.data, Unset):
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if data is not UNSET:
+ field_dict["data"] = data
+ if total is not UNSET:
+ field_dict["total"] = total
+ if has_more is not UNSET:
+ field_dict["has_more"] = has_more
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.anon_key import AnonKey
+ d = dict(src_dict)
+ _data = d.pop("data", UNSET)
+ data: list[AnonKey] | Unset = UNSET
+ if _data is not UNSET:
+ data = []
+ for data_item_data in _data:
+ data_item = AnonKey.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ total = d.pop("total", UNSET)
+
+ has_more = d.pop("has_more", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ list_anon_keys_response_200 = cls(
+ data=data,
+ total=total,
+ has_more=has_more,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ list_anon_keys_response_200.additional_properties = d
+ return list_anon_keys_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_auth_users_status.py b/src/volcano_sdk/_generated/models/list_auth_users_status.py
new file mode 100644
index 00000000..7042df48
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_auth_users_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListAuthUsersStatus = Literal['active', 'banned']
+
+LIST_AUTH_USERS_STATUS_VALUES: set[ListAuthUsersStatus] = { 'active', 'banned', }
+
+def check_list_auth_users_status(value: str) -> ListAuthUsersStatus:
+ if value in LIST_AUTH_USERS_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_AUTH_USERS_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200.py b/src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200.py
new file mode 100644
index 00000000..99a469c9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.list_available_o_auth_providers_response_200_providers_item import ListAvailableOAuthProvidersResponse200ProvidersItem
+
+
+
+
+
+T = TypeVar("T", bound="ListAvailableOAuthProvidersResponse200")
+
+
+
+@_attrs_define
+class ListAvailableOAuthProvidersResponse200:
+ """
+ Attributes:
+ providers (list[ListAvailableOAuthProvidersResponse200ProvidersItem] | Unset):
+ """
+
+ providers: list[ListAvailableOAuthProvidersResponse200ProvidersItem] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.list_available_o_auth_providers_response_200_providers_item import ListAvailableOAuthProvidersResponse200ProvidersItem
+ providers: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.providers, Unset):
+ providers = []
+ for providers_item_data in self.providers:
+ providers_item = providers_item_data.to_dict()
+ providers.append(providers_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if providers is not UNSET:
+ field_dict["providers"] = providers
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.list_available_o_auth_providers_response_200_providers_item import ListAvailableOAuthProvidersResponse200ProvidersItem
+ d = dict(src_dict)
+ _providers = d.pop("providers", UNSET)
+ providers: list[ListAvailableOAuthProvidersResponse200ProvidersItem] | Unset = UNSET
+ if _providers is not UNSET:
+ providers = []
+ for providers_item_data in _providers:
+ providers_item = ListAvailableOAuthProvidersResponse200ProvidersItem.from_dict(providers_item_data)
+
+
+
+ providers.append(providers_item)
+
+
+ list_available_o_auth_providers_response_200 = cls(
+ providers=providers,
+ )
+
+
+ list_available_o_auth_providers_response_200.additional_properties = d
+ return list_available_o_auth_providers_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200_providers_item.py b/src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200_providers_item.py
new file mode 100644
index 00000000..1db9db83
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_available_o_auth_providers_response_200_providers_item.py
@@ -0,0 +1,102 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ListAvailableOAuthProvidersResponse200ProvidersItem")
+
+
+
+@_attrs_define
+class ListAvailableOAuthProvidersResponse200ProvidersItem:
+ """
+ Attributes:
+ id (str | Unset):
+ name (str | Unset):
+ default_scopes (list[str] | Unset):
+ """
+
+ id: str | Unset = UNSET
+ name: str | Unset = UNSET
+ default_scopes: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = self.id
+
+ name = self.name
+
+ default_scopes: list[str] | Unset = UNSET
+ if not isinstance(self.default_scopes, Unset):
+ default_scopes = self.default_scopes
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if id is not UNSET:
+ field_dict["id"] = id
+ if name is not UNSET:
+ field_dict["name"] = name
+ if default_scopes is not UNSET:
+ field_dict["default_scopes"] = default_scopes
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = d.pop("id", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ default_scopes = cast(list[str], d.pop("default_scopes", UNSET))
+
+
+ list_available_o_auth_providers_response_200_providers_item = cls(
+ id=id,
+ name=name,
+ default_scopes=default_scopes,
+ )
+
+
+ list_available_o_auth_providers_response_200_providers_item.additional_properties = d
+ return list_available_o_auth_providers_response_200_providers_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_database_regions_response_200_item.py b/src/volcano_sdk/_generated/models/list_database_regions_response_200_item.py
new file mode 100644
index 00000000..3845a0f0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_database_regions_response_200_item.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ListDatabaseRegionsResponse200Item")
+
+
+
+@_attrs_define
+class ListDatabaseRegionsResponse200Item:
+ """
+ Attributes:
+ id (str | Unset): Region identifier for API usage Example: aws-us-east-1.
+ name (str | Unset): Human-readable region name Example: AWS US East 1 (N. Virginia).
+ """
+
+ id: str | Unset = UNSET
+ name: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = self.id
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if id is not UNSET:
+ field_dict["id"] = id
+ if name is not UNSET:
+ field_dict["name"] = name
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = d.pop("id", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ list_database_regions_response_200_item = cls(
+ id=id,
+ name=name,
+ )
+
+
+ list_database_regions_response_200_item.additional_properties = d
+ return list_database_regions_response_200_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_deployments_operation.py b/src/volcano_sdk/_generated/models/list_deployments_operation.py
new file mode 100644
index 00000000..96278b6d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_deployments_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListDeploymentsOperation = Literal['delete', 'deploy', 'redeploy', 'update']
+
+LIST_DEPLOYMENTS_OPERATION_VALUES: set[ListDeploymentsOperation] = { 'delete', 'deploy', 'redeploy', 'update', }
+
+def check_list_deployments_operation(value: str) -> ListDeploymentsOperation:
+ if value in LIST_DEPLOYMENTS_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_DEPLOYMENTS_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/list_deployments_order.py b/src/volcano_sdk/_generated/models/list_deployments_order.py
new file mode 100644
index 00000000..9908da88
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_deployments_order.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListDeploymentsOrder = Literal['completed_at.asc', 'created_at.desc']
+
+LIST_DEPLOYMENTS_ORDER_VALUES: set[ListDeploymentsOrder] = { 'completed_at.asc', 'created_at.desc', }
+
+def check_list_deployments_order(value: str) -> ListDeploymentsOrder:
+ if value in LIST_DEPLOYMENTS_ORDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_DEPLOYMENTS_ORDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/list_deployments_resource_type.py b/src/volcano_sdk/_generated/models/list_deployments_resource_type.py
new file mode 100644
index 00000000..aa3cb431
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_deployments_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListDeploymentsResourceType = Literal['frontend', 'function']
+
+LIST_DEPLOYMENTS_RESOURCE_TYPE_VALUES: set[ListDeploymentsResourceType] = { 'frontend', 'function', }
+
+def check_list_deployments_resource_type(value: str) -> ListDeploymentsResourceType:
+ if value in LIST_DEPLOYMENTS_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_DEPLOYMENTS_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/list_deployments_status.py b/src/volcano_sdk/_generated/models/list_deployments_status.py
new file mode 100644
index 00000000..85e8eaec
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_deployments_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListDeploymentsStatus = Literal['active', 'degraded', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded']
+
+LIST_DEPLOYMENTS_STATUS_VALUES: set[ListDeploymentsStatus] = { 'active', 'degraded', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded', }
+
+def check_list_deployments_status(value: str) -> ListDeploymentsStatus:
+ if value in LIST_DEPLOYMENTS_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_DEPLOYMENTS_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/list_email_templates_response_200.py b/src/volcano_sdk/_generated/models/list_email_templates_response_200.py
new file mode 100644
index 00000000..bca948dd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_email_templates_response_200.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.email_template import EmailTemplate
+
+
+
+
+
+T = TypeVar("T", bound="ListEmailTemplatesResponse200")
+
+
+
+@_attrs_define
+class ListEmailTemplatesResponse200:
+ """
+ Attributes:
+ data (list[EmailTemplate] | Unset):
+ """
+
+ data: list[EmailTemplate] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.email_template import EmailTemplate
+ data: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.data, Unset):
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if data is not UNSET:
+ field_dict["data"] = data
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.email_template import EmailTemplate
+ d = dict(src_dict)
+ _data = d.pop("data", UNSET)
+ data: list[EmailTemplate] | Unset = UNSET
+ if _data is not UNSET:
+ data = []
+ for data_item_data in _data:
+ data_item = EmailTemplate.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ list_email_templates_response_200 = cls(
+ data=data,
+ )
+
+
+ list_email_templates_response_200.additional_properties = d
+ return list_email_templates_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_o_auth_configs_response_200.py b/src/volcano_sdk/_generated/models/list_o_auth_configs_response_200.py
new file mode 100644
index 00000000..c784b222
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_o_auth_configs_response_200.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.o_auth_config import OAuthConfig
+
+
+
+
+
+T = TypeVar("T", bound="ListOAuthConfigsResponse200")
+
+
+
+@_attrs_define
+class ListOAuthConfigsResponse200:
+ """
+ Attributes:
+ configs (list[OAuthConfig] | Unset):
+ """
+
+ configs: list[OAuthConfig] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.o_auth_config import OAuthConfig
+ configs: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.configs, Unset):
+ configs = []
+ for configs_item_data in self.configs:
+ configs_item = configs_item_data.to_dict()
+ configs.append(configs_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if configs is not UNSET:
+ field_dict["configs"] = configs
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.o_auth_config import OAuthConfig
+ d = dict(src_dict)
+ _configs = d.pop("configs", UNSET)
+ configs: list[OAuthConfig] | Unset = UNSET
+ if _configs is not UNSET:
+ configs = []
+ for configs_item_data in _configs:
+ configs_item = OAuthConfig.from_dict(configs_item_data)
+
+
+
+ configs.append(configs_item)
+
+
+ list_o_auth_configs_response_200 = cls(
+ configs=configs,
+ )
+
+
+ list_o_auth_configs_response_200.additional_properties = d
+ return list_o_auth_configs_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_postgres_versions_response_200_item.py b/src/volcano_sdk/_generated/models/list_postgres_versions_response_200_item.py
new file mode 100644
index 00000000..b5c0703a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_postgres_versions_response_200_item.py
@@ -0,0 +1,105 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ListPostgresVersionsResponse200Item")
+
+
+
+@_attrs_define
+class ListPostgresVersionsResponse200Item:
+ """
+ Attributes:
+ version (str | Unset): PostgreSQL major version number Example: 16.
+ name (str | Unset): Human-readable version name Example: PostgreSQL 16.
+ default (bool | Unset): Whether this is the default version (recommended)
+ deprecated (bool | Unset): Whether this version is deprecated (approaching EOL)
+ """
+
+ version: str | Unset = UNSET
+ name: str | Unset = UNSET
+ default: bool | Unset = UNSET
+ deprecated: bool | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ version = self.version
+
+ name = self.name
+
+ default = self.default
+
+ deprecated = self.deprecated
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if version is not UNSET:
+ field_dict["version"] = version
+ if name is not UNSET:
+ field_dict["name"] = name
+ if default is not UNSET:
+ field_dict["default"] = default
+ if deprecated is not UNSET:
+ field_dict["deprecated"] = deprecated
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ version = d.pop("version", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ default = d.pop("default", UNSET)
+
+ deprecated = d.pop("deprecated", UNSET)
+
+ list_postgres_versions_response_200_item = cls(
+ version=version,
+ name=name,
+ default=default,
+ deprecated=deprecated,
+ )
+
+
+ list_postgres_versions_response_200_item.additional_properties = d
+ return list_postgres_versions_response_200_item
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_project_deployments_resource_type.py b/src/volcano_sdk/_generated/models/list_project_deployments_resource_type.py
new file mode 100644
index 00000000..1576e338
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_project_deployments_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListProjectDeploymentsResourceType = Literal['frontend', 'function']
+
+LIST_PROJECT_DEPLOYMENTS_RESOURCE_TYPE_VALUES: set[ListProjectDeploymentsResourceType] = { 'frontend', 'function', }
+
+def check_list_project_deployments_resource_type(value: str) -> ListProjectDeploymentsResourceType:
+ if value in LIST_PROJECT_DEPLOYMENTS_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_PROJECT_DEPLOYMENTS_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/list_storage_objects_admin_response_200.py b/src/volcano_sdk/_generated/models/list_storage_objects_admin_response_200.py
new file mode 100644
index 00000000..738da3b5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_storage_objects_admin_response_200.py
@@ -0,0 +1,155 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.storage_object_with_bucket import StorageObjectWithBucket
+
+
+
+
+
+T = TypeVar("T", bound="ListStorageObjectsAdminResponse200")
+
+
+
+@_attrs_define
+class ListStorageObjectsAdminResponse200:
+ """
+ Attributes:
+ data (list[StorageObjectWithBucket] | Unset):
+ page (int | Unset):
+ limit (int | Unset):
+ total (int | Unset):
+ has_more (bool | Unset):
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only). Send as
+ `ending_before`.
+ """
+
+ data: list[StorageObjectWithBucket] | Unset = UNSET
+ page: int | Unset = UNSET
+ limit: int | Unset = UNSET
+ total: int | Unset = UNSET
+ has_more: bool | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.storage_object_with_bucket import StorageObjectWithBucket
+ data: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.data, Unset):
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if data is not UNSET:
+ field_dict["data"] = data
+ if page is not UNSET:
+ field_dict["page"] = page
+ if limit is not UNSET:
+ field_dict["limit"] = limit
+ if total is not UNSET:
+ field_dict["total"] = total
+ if has_more is not UNSET:
+ field_dict["has_more"] = has_more
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.storage_object_with_bucket import StorageObjectWithBucket
+ d = dict(src_dict)
+ _data = d.pop("data", UNSET)
+ data: list[StorageObjectWithBucket] | Unset = UNSET
+ if _data is not UNSET:
+ data = []
+ for data_item_data in _data:
+ data_item = StorageObjectWithBucket.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page", UNSET)
+
+ limit = d.pop("limit", UNSET)
+
+ total = d.pop("total", UNSET)
+
+ has_more = d.pop("has_more", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ list_storage_objects_admin_response_200 = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ list_storage_objects_admin_response_200.additional_properties = d
+ return list_storage_objects_admin_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_user_sessions_response_200.py b/src/volcano_sdk/_generated/models/list_user_sessions_response_200.py
new file mode 100644
index 00000000..44d0523a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_user_sessions_response_200.py
@@ -0,0 +1,190 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_session import AuthSession
+
+
+
+
+
+T = TypeVar("T", bound="ListUserSessionsResponse200")
+
+
+
+@_attrs_define
+class ListUserSessionsResponse200:
+ """
+ Attributes:
+ sessions (list[AuthSession] | Unset):
+ total (int | Unset): Total number of sessions
+ page (int | Unset): Current page number
+ limit (int | Unset): Number of sessions per page
+ total_pages (int | Unset): Total number of pages
+ data (list[AuthSession] | Unset): Sessions for this page (cursor pagination only)
+ has_more (bool | Unset): Whether a further page exists (cursor pagination only)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only). Send as
+ `ending_before`.
+ """
+
+ sessions: list[AuthSession] | Unset = UNSET
+ total: int | Unset = UNSET
+ page: int | Unset = UNSET
+ limit: int | Unset = UNSET
+ total_pages: int | Unset = UNSET
+ data: list[AuthSession] | Unset = UNSET
+ has_more: bool | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_session import AuthSession
+ sessions: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.sessions, Unset):
+ sessions = []
+ for sessions_item_data in self.sessions:
+ sessions_item = sessions_item_data.to_dict()
+ sessions.append(sessions_item)
+
+
+
+ total = self.total
+
+ page = self.page
+
+ limit = self.limit
+
+ total_pages = self.total_pages
+
+ data: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.data, Unset):
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ has_more = self.has_more
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if sessions is not UNSET:
+ field_dict["sessions"] = sessions
+ if total is not UNSET:
+ field_dict["total"] = total
+ if page is not UNSET:
+ field_dict["page"] = page
+ if limit is not UNSET:
+ field_dict["limit"] = limit
+ if total_pages is not UNSET:
+ field_dict["total_pages"] = total_pages
+ if data is not UNSET:
+ field_dict["data"] = data
+ if has_more is not UNSET:
+ field_dict["has_more"] = has_more
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_session import AuthSession
+ d = dict(src_dict)
+ _sessions = d.pop("sessions", UNSET)
+ sessions: list[AuthSession] | Unset = UNSET
+ if _sessions is not UNSET:
+ sessions = []
+ for sessions_item_data in _sessions:
+ sessions_item = AuthSession.from_dict(sessions_item_data)
+
+
+
+ sessions.append(sessions_item)
+
+
+ total = d.pop("total", UNSET)
+
+ page = d.pop("page", UNSET)
+
+ limit = d.pop("limit", UNSET)
+
+ total_pages = d.pop("total_pages", UNSET)
+
+ _data = d.pop("data", UNSET)
+ data: list[AuthSession] | Unset = UNSET
+ if _data is not UNSET:
+ data = []
+ for data_item_data in _data:
+ data_item = AuthSession.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ has_more = d.pop("has_more", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ list_user_sessions_response_200 = cls(
+ sessions=sessions,
+ total=total,
+ page=page,
+ limit=limit,
+ total_pages=total_pages,
+ data=data,
+ has_more=has_more,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ list_user_sessions_response_200.additional_properties = d
+ return list_user_sessions_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/list_user_sessions_sort.py b/src/volcano_sdk/_generated/models/list_user_sessions_sort.py
new file mode 100644
index 00000000..6766a766
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_user_sessions_sort.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListUserSessionsSort = Literal['created_at', 'last_activity']
+
+LIST_USER_SESSIONS_SORT_VALUES: set[ListUserSessionsSort] = { 'created_at', 'last_activity', }
+
+def check_list_user_sessions_sort(value: str) -> ListUserSessionsSort:
+ if value in LIST_USER_SESSIONS_SORT_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_USER_SESSIONS_SORT_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/list_user_sessions_status.py b/src/volcano_sdk/_generated/models/list_user_sessions_status.py
new file mode 100644
index 00000000..662226a1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/list_user_sessions_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ListUserSessionsStatus = Literal['active', 'expired']
+
+LIST_USER_SESSIONS_STATUS_VALUES: set[ListUserSessionsStatus] = { 'active', 'expired', }
+
+def check_list_user_sessions_status(value: str) -> ListUserSessionsStatus:
+ if value in LIST_USER_SESSIONS_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIST_USER_SESSIONS_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/live_log_level.py b/src/volcano_sdk/_generated/models/live_log_level.py
new file mode 100644
index 00000000..eed1a61a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/live_log_level.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+LiveLogLevel = Literal['debug', 'error', 'fatal', 'info', 'trace', 'warn']
+
+LIVE_LOG_LEVEL_VALUES: set[LiveLogLevel] = { 'debug', 'error', 'fatal', 'info', 'trace', 'warn', }
+
+def check_live_log_level(value: str) -> LiveLogLevel:
+ if value in LIVE_LOG_LEVEL_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LIVE_LOG_LEVEL_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/log_activity_bucket.py b/src/volcano_sdk/_generated/models/log_activity_bucket.py
new file mode 100644
index 00000000..ffdda773
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_activity_bucket.py
@@ -0,0 +1,116 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.log_activity_bucket_counts import LogActivityBucketCounts
+
+
+
+
+
+T = TypeVar("T", bound="LogActivityBucket")
+
+
+
+@_attrs_define
+class LogActivityBucket:
+ """ Log-event counts for one activity time bucket.
+
+ Attributes:
+ start_time (datetime.datetime): Bucket start time.
+ end_time (datetime.datetime): Bucket end time.
+ counts (LogActivityBucketCounts): Counts grouped by activity dimension.
+ total (int): Total events in this bucket.
+ """
+
+ start_time: datetime.datetime
+ end_time: datetime.datetime
+ counts: LogActivityBucketCounts
+ total: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_activity_bucket_counts import LogActivityBucketCounts
+ start_time = self.start_time.isoformat()
+
+ end_time = self.end_time.isoformat()
+
+ counts = self.counts.to_dict()
+
+ total = self.total
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "start_time": start_time,
+ "end_time": end_time,
+ "counts": counts,
+ "total": total,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_activity_bucket_counts import LogActivityBucketCounts
+ d = dict(src_dict)
+ start_time = datetime.datetime.fromisoformat(d.pop("start_time"))
+
+
+
+
+ end_time = datetime.datetime.fromisoformat(d.pop("end_time"))
+
+
+
+
+ counts = LogActivityBucketCounts.from_dict(d.pop("counts"))
+
+
+
+
+ total = d.pop("total")
+
+ log_activity_bucket = cls(
+ start_time=start_time,
+ end_time=end_time,
+ counts=counts,
+ total=total,
+ )
+
+
+ log_activity_bucket.additional_properties = d
+ return log_activity_bucket
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_activity_bucket_counts.py b/src/volcano_sdk/_generated/models/log_activity_bucket_counts.py
new file mode 100644
index 00000000..c096acb1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_activity_bucket_counts.py
@@ -0,0 +1,113 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.log_activity_bucket_counts_levels import LogActivityBucketCountsLevels
+ from ..models.log_activity_bucket_counts_regions import LogActivityBucketCountsRegions
+ from ..models.log_activity_bucket_counts_resource_ids import LogActivityBucketCountsResourceIds
+
+
+
+
+
+T = TypeVar("T", bound="LogActivityBucketCounts")
+
+
+
+@_attrs_define
+class LogActivityBucketCounts:
+ """ Counts grouped by activity dimension.
+
+ Attributes:
+ levels (LogActivityBucketCountsLevels): Counts by normalized log level.
+ regions (LogActivityBucketCountsRegions): Counts by event region.
+ resource_ids (LogActivityBucketCountsResourceIds): Counts by resource ID.
+ """
+
+ levels: LogActivityBucketCountsLevels
+ regions: LogActivityBucketCountsRegions
+ resource_ids: LogActivityBucketCountsResourceIds
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_activity_bucket_counts_levels import LogActivityBucketCountsLevels
+ from ..models.log_activity_bucket_counts_regions import LogActivityBucketCountsRegions
+ from ..models.log_activity_bucket_counts_resource_ids import LogActivityBucketCountsResourceIds
+ levels = self.levels.to_dict()
+
+ regions = self.regions.to_dict()
+
+ resource_ids = self.resource_ids.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "levels": levels,
+ "regions": regions,
+ "resource_ids": resource_ids,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_activity_bucket_counts_levels import LogActivityBucketCountsLevels
+ from ..models.log_activity_bucket_counts_regions import LogActivityBucketCountsRegions
+ from ..models.log_activity_bucket_counts_resource_ids import LogActivityBucketCountsResourceIds
+ d = dict(src_dict)
+ levels = LogActivityBucketCountsLevels.from_dict(d.pop("levels"))
+
+
+
+
+ regions = LogActivityBucketCountsRegions.from_dict(d.pop("regions"))
+
+
+
+
+ resource_ids = LogActivityBucketCountsResourceIds.from_dict(d.pop("resource_ids"))
+
+
+
+
+ log_activity_bucket_counts = cls(
+ levels=levels,
+ regions=regions,
+ resource_ids=resource_ids,
+ )
+
+
+ log_activity_bucket_counts.additional_properties = d
+ return log_activity_bucket_counts
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_activity_bucket_counts_levels.py b/src/volcano_sdk/_generated/models/log_activity_bucket_counts_levels.py
new file mode 100644
index 00000000..ab7b6380
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_activity_bucket_counts_levels.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="LogActivityBucketCountsLevels")
+
+
+
+@_attrs_define
+class LogActivityBucketCountsLevels:
+ """ Counts by normalized log level.
+
+ """
+
+ additional_properties: dict[str, int] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ log_activity_bucket_counts_levels = cls(
+ )
+
+
+ log_activity_bucket_counts_levels.additional_properties = d
+ return log_activity_bucket_counts_levels
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> int:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: int) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_activity_bucket_counts_regions.py b/src/volcano_sdk/_generated/models/log_activity_bucket_counts_regions.py
new file mode 100644
index 00000000..3a059a9f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_activity_bucket_counts_regions.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="LogActivityBucketCountsRegions")
+
+
+
+@_attrs_define
+class LogActivityBucketCountsRegions:
+ """ Counts by event region.
+
+ """
+
+ additional_properties: dict[str, int] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ log_activity_bucket_counts_regions = cls(
+ )
+
+
+ log_activity_bucket_counts_regions.additional_properties = d
+ return log_activity_bucket_counts_regions
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> int:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: int) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_activity_bucket_counts_resource_ids.py b/src/volcano_sdk/_generated/models/log_activity_bucket_counts_resource_ids.py
new file mode 100644
index 00000000..2fd7c5c8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_activity_bucket_counts_resource_ids.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="LogActivityBucketCountsResourceIds")
+
+
+
+@_attrs_define
+class LogActivityBucketCountsResourceIds:
+ """ Counts by resource ID.
+
+ """
+
+ additional_properties: dict[str, int] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ log_activity_bucket_counts_resource_ids = cls(
+ )
+
+
+ log_activity_bucket_counts_resource_ids.additional_properties = d
+ return log_activity_bucket_counts_resource_ids
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> int:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: int) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_activity_request.py b/src/volcano_sdk/_generated/models/log_activity_request.py
new file mode 100644
index 00000000..b77a6970
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_activity_request.py
@@ -0,0 +1,168 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+
+
+
+
+
+T = TypeVar("T", bound="LogActivityRequest")
+
+
+
+@_attrs_define
+class LogActivityRequest:
+ """ Activity request for bucketed log counts.
+
+ Attributes:
+ resource (LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource): Resource
+ selectors for project log reads.
+ q (str | Unset): Optional activity query. Supports quoted text, implicit AND, AND/OR/NOT, parentheses, and
+ fields such as `level`, `region`, `invocation.id`, `resource.id`, `resource.name`, `function`, `frontend`,
+ `database`, and `body`.
+ start_time (datetime.datetime | Unset): Start time.
+ end_time (datetime.datetime | Unset): End time.
+ bucket_count (int | Unset): Number of activity buckets to return.
+ """
+
+ resource: LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource
+ q: str | Unset = UNSET
+ start_time: datetime.datetime | Unset = UNSET
+ end_time: datetime.datetime | Unset = UNSET
+ bucket_count: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+ resource: dict[str, Any]
+ if isinstance(self.resource, LogFunctionRequestResource):
+ resource = self.resource.to_dict()
+ elif isinstance(self.resource, LogFrontendRequestResource):
+ resource = self.resource.to_dict()
+ else:
+ resource = self.resource.to_dict()
+
+
+ q = self.q
+
+ start_time: str | Unset = UNSET
+ if not isinstance(self.start_time, Unset):
+ start_time = self.start_time.isoformat()
+
+ end_time: str | Unset = UNSET
+ if not isinstance(self.end_time, Unset):
+ end_time = self.end_time.isoformat()
+
+ bucket_count = self.bucket_count
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "resource": resource,
+ })
+ if q is not UNSET:
+ field_dict["q"] = q
+ if start_time is not UNSET:
+ field_dict["start_time"] = start_time
+ if end_time is not UNSET:
+ field_dict["end_time"] = end_time
+ if bucket_count is not UNSET:
+ field_dict["bucket_count"] = bucket_count
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+ d = dict(src_dict)
+ def _parse_resource(data: object) -> LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_0 = LogFunctionRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_1 = LogFrontendRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_1
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_2 = LogDatabaseRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_2
+
+ resource = _parse_resource(d.pop("resource"))
+
+
+ q = d.pop("q", UNSET)
+
+ _start_time = d.pop("start_time", UNSET)
+ start_time: datetime.datetime | Unset
+ if isinstance(_start_time, Unset):
+ start_time = UNSET
+ else:
+ start_time = datetime.datetime.fromisoformat(_start_time)
+
+
+
+
+ _end_time = d.pop("end_time", UNSET)
+ end_time: datetime.datetime | Unset
+ if isinstance(_end_time, Unset):
+ end_time = UNSET
+ else:
+ end_time = datetime.datetime.fromisoformat(_end_time)
+
+
+
+
+ bucket_count = d.pop("bucket_count", UNSET)
+
+ log_activity_request = cls(
+ resource=resource,
+ q=q,
+ start_time=start_time,
+ end_time=end_time,
+ bucket_count=bucket_count,
+ )
+
+ return log_activity_request
+
diff --git a/src/volcano_sdk/_generated/models/log_activity_response.py b/src/volcano_sdk/_generated/models/log_activity_response.py
new file mode 100644
index 00000000..c2d60cd9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_activity_response.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.log_activity_bucket import LogActivityBucket
+
+
+
+
+
+T = TypeVar("T", bound="LogActivityResponse")
+
+
+
+@_attrs_define
+class LogActivityResponse:
+ """ Bucketed runtime log activity.
+
+ Attributes:
+ data (list[LogActivityBucket]):
+ total (int): Total events counted across all buckets.
+ """
+
+ data: list[LogActivityBucket]
+ total: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_activity_bucket import LogActivityBucket
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ total = self.total
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "total": total,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_activity_bucket import LogActivityBucket
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = LogActivityBucket.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ total = d.pop("total")
+
+ log_activity_response = cls(
+ data=data,
+ total=total,
+ )
+
+
+ log_activity_response.additional_properties = d
+ return log_activity_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_database_request_resource.py b/src/volcano_sdk/_generated/models/log_database_request_resource.py
new file mode 100644
index 00000000..babeca52
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_database_request_resource.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.log_database_request_resource_type import check_log_database_request_resource_type
+from ..models.log_database_request_resource_type import LogDatabaseRequestResourceType
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="LogDatabaseRequestResource")
+
+
+
+@_attrs_define
+class LogDatabaseRequestResource:
+ """ Database runtime log resource selector. Deployment logs are not supported for databases.
+
+ Attributes:
+ type_ (LogDatabaseRequestResourceType): Resource type to read logs for.
+ ids (list[UUID] | Unset): Optional database identifiers. Omit or send an empty array to include every database
+ in the project.
+ """
+
+ type_: LogDatabaseRequestResourceType
+ ids: list[UUID] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ type_: str = self.type_
+
+ ids: list[str] | Unset = UNSET
+ if not isinstance(self.ids, Unset):
+ ids = []
+ for ids_item_data in self.ids:
+ ids_item = str(ids_item_data)
+ ids.append(ids_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "type": type_,
+ })
+ if ids is not UNSET:
+ field_dict["ids"] = ids
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ type_ = check_log_database_request_resource_type(d.pop("type"))
+
+
+
+
+ _ids = d.pop("ids", UNSET)
+ ids: list[UUID] | Unset = UNSET
+ if _ids is not UNSET:
+ ids = []
+ for ids_item_data in _ids:
+ ids_item = UUID(ids_item_data)
+
+
+
+ ids.append(ids_item)
+
+
+ log_database_request_resource = cls(
+ type_=type_,
+ ids=ids,
+ )
+
+ return log_database_request_resource
+
diff --git a/src/volcano_sdk/_generated/models/log_database_request_resource_type.py b/src/volcano_sdk/_generated/models/log_database_request_resource_type.py
new file mode 100644
index 00000000..e180b5f5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_database_request_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+LogDatabaseRequestResourceType = Literal['database']
+
+LOG_DATABASE_REQUEST_RESOURCE_TYPE_VALUES: set[LogDatabaseRequestResourceType] = { 'database', }
+
+def check_log_database_request_resource_type(value: str) -> LogDatabaseRequestResourceType:
+ if value in LOG_DATABASE_REQUEST_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LOG_DATABASE_REQUEST_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/log_deployment.py b/src/volcano_sdk/_generated/models/log_deployment.py
new file mode 100644
index 00000000..a5630473
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_deployment.py
@@ -0,0 +1,105 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.log_deployment_stage import check_log_deployment_stage
+from ..models.log_deployment_stage import LogDeploymentStage
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="LogDeployment")
+
+
+
+@_attrs_define
+class LogDeployment:
+ """ Deployment context associated with a historical deployment log event.
+
+ Attributes:
+ id (UUID): Deployment ID associated with the log event.
+ stage (LogDeploymentStage | Unset): Deployment stage that produced the log event, when available.
+ """
+
+ id: UUID
+ stage: LogDeploymentStage | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ stage: str | Unset = UNSET
+ if not isinstance(self.stage, Unset):
+ stage = self.stage
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ })
+ if stage is not UNSET:
+ field_dict["stage"] = stage
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ _stage = d.pop("stage", UNSET)
+ stage: LogDeploymentStage | Unset
+ if isinstance(_stage, Unset):
+ stage = UNSET
+ else:
+ stage = check_log_deployment_stage(_stage)
+
+
+
+
+ log_deployment = cls(
+ id=id,
+ stage=stage,
+ )
+
+
+ log_deployment.additional_properties = d
+ return log_deployment
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_deployment_request_selector.py b/src/volcano_sdk/_generated/models/log_deployment_request_selector.py
new file mode 100644
index 00000000..77599d81
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_deployment_request_selector.py
@@ -0,0 +1,81 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="LogDeploymentRequestSelector")
+
+
+
+@_attrs_define
+class LogDeploymentRequestSelector:
+ """ Deployment log selector for deployable resources.
+
+ Attributes:
+ ids (list[UUID] | Unset): Optional deployment identifiers. Omit or send an empty array to include every
+ deployment for the selected resources.
+ """
+
+ ids: list[UUID] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ ids: list[str] | Unset = UNSET
+ if not isinstance(self.ids, Unset):
+ ids = []
+ for ids_item_data in self.ids:
+ ids_item = str(ids_item_data)
+ ids.append(ids_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if ids is not UNSET:
+ field_dict["ids"] = ids
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ _ids = d.pop("ids", UNSET)
+ ids: list[UUID] | Unset = UNSET
+ if _ids is not UNSET:
+ ids = []
+ for ids_item_data in _ids:
+ ids_item = UUID(ids_item_data)
+
+
+
+ ids.append(ids_item)
+
+
+ log_deployment_request_selector = cls(
+ ids=ids,
+ )
+
+ return log_deployment_request_selector
+
diff --git a/src/volcano_sdk/_generated/models/log_deployment_stage.py b/src/volcano_sdk/_generated/models/log_deployment_stage.py
new file mode 100644
index 00000000..0805a632
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_deployment_stage.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+LogDeploymentStage = Literal['compile', 'publish']
+
+LOG_DEPLOYMENT_STAGE_VALUES: set[LogDeploymentStage] = { 'compile', 'publish', }
+
+def check_log_deployment_stage(value: str) -> LogDeploymentStage:
+ if value in LOG_DEPLOYMENT_STAGE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LOG_DEPLOYMENT_STAGE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/log_event.py b/src/volcano_sdk/_generated/models/log_event.py
new file mode 100644
index 00000000..2fe9e04f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_event.py
@@ -0,0 +1,222 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.live_log_level import check_live_log_level
+from ..models.live_log_level import LiveLogLevel
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.log_deployment import LogDeployment
+ from ..models.log_event_body_type_1 import LogEventBodyType1
+ from ..models.log_resource import LogResource
+
+
+
+
+
+T = TypeVar("T", bound="LogEvent")
+
+
+
+@_attrs_define
+class LogEvent:
+ """ Historical log event returned by log APIs.
+
+ Attributes:
+ timestamp (datetime.datetime): Event timestamp.
+ body (bool | float | list[Any] | LogEventBodyType1 | None | str): Application log value. JSON arguments retain
+ their JSON type. Strings containing a serialized JSON object or array are normalized to that object or array;
+ all other strings remain strings.
+ id (str | Unset): Opaque stable log event ID for pagination, deduplication, and display.
+ level (LiveLogLevel | Unset): Canonical lowercase function runtime log level.
+ region (str | Unset): Region where this log event originated.
+ resource (LogResource | Unset): Resource that owns a historical log event.
+ deployment (LogDeployment | Unset): Deployment context associated with a historical deployment log event.
+ invocation_id (str | Unset): Function invocation ID associated with this log event, when available.
+ """
+
+ timestamp: datetime.datetime
+ body: bool | float | list[Any] | LogEventBodyType1 | None | str
+ id: str | Unset = UNSET
+ level: LiveLogLevel | Unset = UNSET
+ region: str | Unset = UNSET
+ resource: LogResource | Unset = UNSET
+ deployment: LogDeployment | Unset = UNSET
+ invocation_id: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_deployment import LogDeployment
+ from ..models.log_event_body_type_1 import LogEventBodyType1
+ from ..models.log_resource import LogResource
+ timestamp = self.timestamp.isoformat()
+
+ body: bool | dict[str, Any] | float | list[Any] | None | str
+ if isinstance(self.body, LogEventBodyType1):
+ body = self.body.to_dict()
+ elif isinstance(self.body, list):
+ body = self.body
+
+
+ else:
+ body = self.body
+
+ id = self.id
+
+ level: str | Unset = UNSET
+ if not isinstance(self.level, Unset):
+ level = self.level
+
+
+ region = self.region
+
+ resource: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.resource, Unset):
+ resource = self.resource.to_dict()
+
+ deployment: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.deployment, Unset):
+ deployment = self.deployment.to_dict()
+
+ invocation_id = self.invocation_id
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "timestamp": timestamp,
+ "body": body,
+ })
+ if id is not UNSET:
+ field_dict["id"] = id
+ if level is not UNSET:
+ field_dict["level"] = level
+ if region is not UNSET:
+ field_dict["region"] = region
+ if resource is not UNSET:
+ field_dict["resource"] = resource
+ if deployment is not UNSET:
+ field_dict["deployment"] = deployment
+ if invocation_id is not UNSET:
+ field_dict["invocation_id"] = invocation_id
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_deployment import LogDeployment
+ from ..models.log_event_body_type_1 import LogEventBodyType1
+ from ..models.log_resource import LogResource
+ d = dict(src_dict)
+ timestamp = datetime.datetime.fromisoformat(d.pop("timestamp"))
+
+
+
+
+ def _parse_body(data: object) -> bool | float | list[Any] | LogEventBodyType1 | None | str:
+ if data is None:
+ return data
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ body_type_1 = LogEventBodyType1.from_dict(data)
+
+
+
+ return body_type_1
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ try:
+ if not isinstance(data, list):
+ raise TypeError()
+ body_type_2 = cast(list[Any], data)
+
+ return body_type_2
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(bool | float | list[Any] | LogEventBodyType1 | None | str, data)
+
+ body = _parse_body(d.pop("body"))
+
+
+ id = d.pop("id", UNSET)
+
+ _level = d.pop("level", UNSET)
+ level: LiveLogLevel | Unset
+ if isinstance(_level, Unset):
+ level = UNSET
+ else:
+ level = check_live_log_level(_level)
+
+
+
+
+ region = d.pop("region", UNSET)
+
+ _resource = d.pop("resource", UNSET)
+ resource: LogResource | Unset
+ if isinstance(_resource, Unset):
+ resource = UNSET
+ else:
+ resource = LogResource.from_dict(_resource)
+
+
+
+
+ _deployment = d.pop("deployment", UNSET)
+ deployment: LogDeployment | Unset
+ if isinstance(_deployment, Unset):
+ deployment = UNSET
+ else:
+ deployment = LogDeployment.from_dict(_deployment)
+
+
+
+
+ invocation_id = d.pop("invocation_id", UNSET)
+
+ log_event = cls(
+ timestamp=timestamp,
+ body=body,
+ id=id,
+ level=level,
+ region=region,
+ resource=resource,
+ deployment=deployment,
+ invocation_id=invocation_id,
+ )
+
+
+ log_event.additional_properties = d
+ return log_event
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_event_body_type_1.py b/src/volcano_sdk/_generated/models/log_event_body_type_1.py
new file mode 100644
index 00000000..e66dc8bb
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_event_body_type_1.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="LogEventBodyType1")
+
+
+
+@_attrs_define
+class LogEventBodyType1:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ log_event_body_type_1 = cls(
+ )
+
+
+ log_event_body_type_1.additional_properties = d
+ return log_event_body_type_1
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_frontend_request_resource.py b/src/volcano_sdk/_generated/models/log_frontend_request_resource.py
new file mode 100644
index 00000000..054dc82b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_frontend_request_resource.py
@@ -0,0 +1,117 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.log_frontend_request_resource_type import check_log_frontend_request_resource_type
+from ..models.log_frontend_request_resource_type import LogFrontendRequestResourceType
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+if TYPE_CHECKING:
+ from ..models.log_deployment_request_selector import LogDeploymentRequestSelector
+
+
+
+
+
+T = TypeVar("T", bound="LogFrontendRequestResource")
+
+
+
+@_attrs_define
+class LogFrontendRequestResource:
+ """ Frontend log resource selector.
+
+ Attributes:
+ type_ (LogFrontendRequestResourceType): Resource type to read logs for.
+ ids (list[UUID] | Unset): Optional frontend identifiers. Omit or send an empty array to include every frontend
+ in the project.
+ deployments (LogDeploymentRequestSelector | Unset): Deployment log selector for deployable resources.
+ """
+
+ type_: LogFrontendRequestResourceType
+ ids: list[UUID] | Unset = UNSET
+ deployments: LogDeploymentRequestSelector | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_deployment_request_selector import LogDeploymentRequestSelector
+ type_: str = self.type_
+
+ ids: list[str] | Unset = UNSET
+ if not isinstance(self.ids, Unset):
+ ids = []
+ for ids_item_data in self.ids:
+ ids_item = str(ids_item_data)
+ ids.append(ids_item)
+
+
+
+ deployments: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.deployments, Unset):
+ deployments = self.deployments.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "type": type_,
+ })
+ if ids is not UNSET:
+ field_dict["ids"] = ids
+ if deployments is not UNSET:
+ field_dict["deployments"] = deployments
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_deployment_request_selector import LogDeploymentRequestSelector
+ d = dict(src_dict)
+ type_ = check_log_frontend_request_resource_type(d.pop("type"))
+
+
+
+
+ _ids = d.pop("ids", UNSET)
+ ids: list[UUID] | Unset = UNSET
+ if _ids is not UNSET:
+ ids = []
+ for ids_item_data in _ids:
+ ids_item = UUID(ids_item_data)
+
+
+
+ ids.append(ids_item)
+
+
+ _deployments = d.pop("deployments", UNSET)
+ deployments: LogDeploymentRequestSelector | Unset
+ if isinstance(_deployments, Unset):
+ deployments = UNSET
+ else:
+ deployments = LogDeploymentRequestSelector.from_dict(_deployments)
+
+
+
+
+ log_frontend_request_resource = cls(
+ type_=type_,
+ ids=ids,
+ deployments=deployments,
+ )
+
+ return log_frontend_request_resource
+
diff --git a/src/volcano_sdk/_generated/models/log_frontend_request_resource_type.py b/src/volcano_sdk/_generated/models/log_frontend_request_resource_type.py
new file mode 100644
index 00000000..b4e16711
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_frontend_request_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+LogFrontendRequestResourceType = Literal['frontend']
+
+LOG_FRONTEND_REQUEST_RESOURCE_TYPE_VALUES: set[LogFrontendRequestResourceType] = { 'frontend', }
+
+def check_log_frontend_request_resource_type(value: str) -> LogFrontendRequestResourceType:
+ if value in LOG_FRONTEND_REQUEST_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LOG_FRONTEND_REQUEST_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/log_function_request_resource.py b/src/volcano_sdk/_generated/models/log_function_request_resource.py
new file mode 100644
index 00000000..b6a89ec8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_function_request_resource.py
@@ -0,0 +1,117 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.log_function_request_resource_type import check_log_function_request_resource_type
+from ..models.log_function_request_resource_type import LogFunctionRequestResourceType
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+if TYPE_CHECKING:
+ from ..models.log_deployment_request_selector import LogDeploymentRequestSelector
+
+
+
+
+
+T = TypeVar("T", bound="LogFunctionRequestResource")
+
+
+
+@_attrs_define
+class LogFunctionRequestResource:
+ """ Edge Function log resource selector.
+
+ Attributes:
+ type_ (LogFunctionRequestResourceType): Resource type to read logs for.
+ ids (list[UUID] | Unset): Optional function identifiers. Omit or send an empty array to include every function
+ in the project.
+ deployments (LogDeploymentRequestSelector | Unset): Deployment log selector for deployable resources.
+ """
+
+ type_: LogFunctionRequestResourceType
+ ids: list[UUID] | Unset = UNSET
+ deployments: LogDeploymentRequestSelector | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_deployment_request_selector import LogDeploymentRequestSelector
+ type_: str = self.type_
+
+ ids: list[str] | Unset = UNSET
+ if not isinstance(self.ids, Unset):
+ ids = []
+ for ids_item_data in self.ids:
+ ids_item = str(ids_item_data)
+ ids.append(ids_item)
+
+
+
+ deployments: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.deployments, Unset):
+ deployments = self.deployments.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "type": type_,
+ })
+ if ids is not UNSET:
+ field_dict["ids"] = ids
+ if deployments is not UNSET:
+ field_dict["deployments"] = deployments
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_deployment_request_selector import LogDeploymentRequestSelector
+ d = dict(src_dict)
+ type_ = check_log_function_request_resource_type(d.pop("type"))
+
+
+
+
+ _ids = d.pop("ids", UNSET)
+ ids: list[UUID] | Unset = UNSET
+ if _ids is not UNSET:
+ ids = []
+ for ids_item_data in _ids:
+ ids_item = UUID(ids_item_data)
+
+
+
+ ids.append(ids_item)
+
+
+ _deployments = d.pop("deployments", UNSET)
+ deployments: LogDeploymentRequestSelector | Unset
+ if isinstance(_deployments, Unset):
+ deployments = UNSET
+ else:
+ deployments = LogDeploymentRequestSelector.from_dict(_deployments)
+
+
+
+
+ log_function_request_resource = cls(
+ type_=type_,
+ ids=ids,
+ deployments=deployments,
+ )
+
+ return log_function_request_resource
+
diff --git a/src/volcano_sdk/_generated/models/log_function_request_resource_type.py b/src/volcano_sdk/_generated/models/log_function_request_resource_type.py
new file mode 100644
index 00000000..abb7c025
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_function_request_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+LogFunctionRequestResourceType = Literal['function']
+
+LOG_FUNCTION_REQUEST_RESOURCE_TYPE_VALUES: set[LogFunctionRequestResourceType] = { 'function', }
+
+def check_log_function_request_resource_type(value: str) -> LogFunctionRequestResourceType:
+ if value in LOG_FUNCTION_REQUEST_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LOG_FUNCTION_REQUEST_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/log_resource.py b/src/volcano_sdk/_generated/models/log_resource.py
new file mode 100644
index 00000000..eac4b4f0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_resource.py
@@ -0,0 +1,105 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.log_resource_type import check_log_resource_type
+from ..models.log_resource_type import LogResourceType
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="LogResource")
+
+
+
+@_attrs_define
+class LogResource:
+ """ Resource that owns a historical log event.
+
+ Attributes:
+ type_ (LogResourceType): Resource type that owns the log event.
+ id (UUID): Resource ID that owns the log event.
+ name (str | Unset): Resource name associated with the log event, when available.
+ """
+
+ type_: LogResourceType
+ id: UUID
+ name: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ type_: str = self.type_
+
+ id = str(self.id)
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "type": type_,
+ "id": id,
+ })
+ if name is not UNSET:
+ field_dict["name"] = name
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ type_ = check_log_resource_type(d.pop("type"))
+
+
+
+
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name", UNSET)
+
+ log_resource = cls(
+ type_=type_,
+ id=id,
+ name=name,
+ )
+
+
+ log_resource.additional_properties = d
+ return log_resource
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_resource_type.py b/src/volcano_sdk/_generated/models/log_resource_type.py
new file mode 100644
index 00000000..fbcf58c4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+LogResourceType = Literal['database', 'frontend', 'function']
+
+LOG_RESOURCE_TYPE_VALUES: set[LogResourceType] = { 'database', 'frontend', 'function', }
+
+def check_log_resource_type(value: str) -> LogResourceType:
+ if value in LOG_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {LOG_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/log_search_event.py b/src/volcano_sdk/_generated/models/log_search_event.py
new file mode 100644
index 00000000..577457c8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_search_event.py
@@ -0,0 +1,212 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.live_log_level import check_live_log_level
+from ..models.live_log_level import LiveLogLevel
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.log_deployment import LogDeployment
+ from ..models.log_event_body_type_1 import LogEventBodyType1
+ from ..models.log_resource import LogResource
+
+
+
+
+
+T = TypeVar("T", bound="LogSearchEvent")
+
+
+
+@_attrs_define
+class LogSearchEvent:
+ """
+ Attributes:
+ timestamp (datetime.datetime): Event timestamp.
+ body (bool | float | list[Any] | LogEventBodyType1 | None | str): Application log value. JSON arguments retain
+ their JSON type. Strings containing a serialized JSON object or array are normalized to that object or array;
+ all other strings remain strings.
+ id (str): Opaque stable log event ID for pagination, deduplication, and display.
+ resource (LogResource): Resource that owns a historical log event.
+ level (LiveLogLevel | Unset): Canonical lowercase function runtime log level.
+ region (str | Unset): Region where this log event originated.
+ deployment (LogDeployment | Unset): Deployment context associated with a historical deployment log event.
+ invocation_id (str | Unset): Function invocation ID associated with this log event, when available.
+ """
+
+ timestamp: datetime.datetime
+ body: bool | float | list[Any] | LogEventBodyType1 | None | str
+ id: str
+ resource: LogResource
+ level: LiveLogLevel | Unset = UNSET
+ region: str | Unset = UNSET
+ deployment: LogDeployment | Unset = UNSET
+ invocation_id: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_deployment import LogDeployment
+ from ..models.log_event_body_type_1 import LogEventBodyType1
+ from ..models.log_resource import LogResource
+ timestamp = self.timestamp.isoformat()
+
+ body: bool | dict[str, Any] | float | list[Any] | None | str
+ if isinstance(self.body, LogEventBodyType1):
+ body = self.body.to_dict()
+ elif isinstance(self.body, list):
+ body = self.body
+
+
+ else:
+ body = self.body
+
+ id = self.id
+
+ resource = self.resource.to_dict()
+
+ level: str | Unset = UNSET
+ if not isinstance(self.level, Unset):
+ level = self.level
+
+
+ region = self.region
+
+ deployment: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.deployment, Unset):
+ deployment = self.deployment.to_dict()
+
+ invocation_id = self.invocation_id
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "timestamp": timestamp,
+ "body": body,
+ "id": id,
+ "resource": resource,
+ })
+ if level is not UNSET:
+ field_dict["level"] = level
+ if region is not UNSET:
+ field_dict["region"] = region
+ if deployment is not UNSET:
+ field_dict["deployment"] = deployment
+ if invocation_id is not UNSET:
+ field_dict["invocation_id"] = invocation_id
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_deployment import LogDeployment
+ from ..models.log_event_body_type_1 import LogEventBodyType1
+ from ..models.log_resource import LogResource
+ d = dict(src_dict)
+ timestamp = datetime.datetime.fromisoformat(d.pop("timestamp"))
+
+
+
+
+ def _parse_body(data: object) -> bool | float | list[Any] | LogEventBodyType1 | None | str:
+ if data is None:
+ return data
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ body_type_1 = LogEventBodyType1.from_dict(data)
+
+
+
+ return body_type_1
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ try:
+ if not isinstance(data, list):
+ raise TypeError()
+ body_type_2 = cast(list[Any], data)
+
+ return body_type_2
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(bool | float | list[Any] | LogEventBodyType1 | None | str, data)
+
+ body = _parse_body(d.pop("body"))
+
+
+ id = d.pop("id")
+
+ resource = LogResource.from_dict(d.pop("resource"))
+
+
+
+
+ _level = d.pop("level", UNSET)
+ level: LiveLogLevel | Unset
+ if isinstance(_level, Unset):
+ level = UNSET
+ else:
+ level = check_live_log_level(_level)
+
+
+
+
+ region = d.pop("region", UNSET)
+
+ _deployment = d.pop("deployment", UNSET)
+ deployment: LogDeployment | Unset
+ if isinstance(_deployment, Unset):
+ deployment = UNSET
+ else:
+ deployment = LogDeployment.from_dict(_deployment)
+
+
+
+
+ invocation_id = d.pop("invocation_id", UNSET)
+
+ log_search_event = cls(
+ timestamp=timestamp,
+ body=body,
+ id=id,
+ resource=resource,
+ level=level,
+ region=region,
+ deployment=deployment,
+ invocation_id=invocation_id,
+ )
+
+
+ log_search_event.additional_properties = d
+ return log_search_event
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_search_request.py b/src/volcano_sdk/_generated/models/log_search_request.py
new file mode 100644
index 00000000..5e3b587f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_search_request.py
@@ -0,0 +1,177 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+
+
+
+
+
+T = TypeVar("T", bound="LogSearchRequest")
+
+
+
+@_attrs_define
+class LogSearchRequest:
+ """ Search request for project logs.
+
+ Attributes:
+ resource (LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource): Resource
+ selectors for project log reads.
+ q (str | Unset): Optional log query. Supports quoted text, implicit AND, AND/OR/NOT, parentheses, and fields
+ such as `level`, `region`, `invocation.id`, `resource.id`, `resource.name`, `function`, `frontend`, `database`,
+ and `body`.
+ start_time (datetime.datetime | Unset): Start time.
+ end_time (datetime.datetime | Unset): End time.
+ limit (int | Unset): Maximum number of records to return. Default: 100.
+ cursor (str | Unset): Opaque pagination cursor from the previous response's `next_cursor`.
+ """
+
+ resource: LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource
+ q: str | Unset = UNSET
+ start_time: datetime.datetime | Unset = UNSET
+ end_time: datetime.datetime | Unset = UNSET
+ limit: int | Unset = 100
+ cursor: str | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+ resource: dict[str, Any]
+ if isinstance(self.resource, LogFunctionRequestResource):
+ resource = self.resource.to_dict()
+ elif isinstance(self.resource, LogFrontendRequestResource):
+ resource = self.resource.to_dict()
+ else:
+ resource = self.resource.to_dict()
+
+
+ q = self.q
+
+ start_time: str | Unset = UNSET
+ if not isinstance(self.start_time, Unset):
+ start_time = self.start_time.isoformat()
+
+ end_time: str | Unset = UNSET
+ if not isinstance(self.end_time, Unset):
+ end_time = self.end_time.isoformat()
+
+ limit = self.limit
+
+ cursor = self.cursor
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "resource": resource,
+ })
+ if q is not UNSET:
+ field_dict["q"] = q
+ if start_time is not UNSET:
+ field_dict["start_time"] = start_time
+ if end_time is not UNSET:
+ field_dict["end_time"] = end_time
+ if limit is not UNSET:
+ field_dict["limit"] = limit
+ if cursor is not UNSET:
+ field_dict["cursor"] = cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+ d = dict(src_dict)
+ def _parse_resource(data: object) -> LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_0 = LogFunctionRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_1 = LogFrontendRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_1
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_2 = LogDatabaseRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_2
+
+ resource = _parse_resource(d.pop("resource"))
+
+
+ q = d.pop("q", UNSET)
+
+ _start_time = d.pop("start_time", UNSET)
+ start_time: datetime.datetime | Unset
+ if isinstance(_start_time, Unset):
+ start_time = UNSET
+ else:
+ start_time = datetime.datetime.fromisoformat(_start_time)
+
+
+
+
+ _end_time = d.pop("end_time", UNSET)
+ end_time: datetime.datetime | Unset
+ if isinstance(_end_time, Unset):
+ end_time = UNSET
+ else:
+ end_time = datetime.datetime.fromisoformat(_end_time)
+
+
+
+
+ limit = d.pop("limit", UNSET)
+
+ cursor = d.pop("cursor", UNSET)
+
+ log_search_request = cls(
+ resource=resource,
+ q=q,
+ start_time=start_time,
+ end_time=end_time,
+ limit=limit,
+ cursor=cursor,
+ )
+
+ return log_search_request
+
diff --git a/src/volcano_sdk/_generated/models/log_search_response.py b/src/volcano_sdk/_generated/models/log_search_response.py
new file mode 100644
index 00000000..467ab209
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_search_response.py
@@ -0,0 +1,121 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.log_search_event import LogSearchEvent
+
+
+
+
+
+T = TypeVar("T", bound="LogSearchResponse")
+
+
+
+@_attrs_define
+class LogSearchResponse:
+ """ Paginated project runtime log search response.
+
+ Attributes:
+ data (list[LogSearchEvent]): Array of log events sorted by timestamp, newest first.
+ limit (int): Number of items requested per page.
+ has_more (bool): Whether there are more log events available.
+ next_cursor (str | Unset): Opaque cursor for the next page. Send this value as `cursor` on the next request.
+ """
+
+ data: list[LogSearchEvent]
+ limit: int
+ has_more: bool
+ next_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_search_event import LogSearchEvent
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ limit = self.limit
+
+ has_more = self.has_more
+
+ next_cursor = self.next_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "limit": limit,
+ "has_more": has_more,
+ })
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_search_event import LogSearchEvent
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = LogSearchEvent.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ limit = d.pop("limit")
+
+ has_more = d.pop("has_more")
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ log_search_response = cls(
+ data=data,
+ limit=limit,
+ has_more=has_more,
+ next_cursor=next_cursor,
+ )
+
+
+ log_search_response.additional_properties = d
+ return log_search_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/log_stream_request.py b/src/volcano_sdk/_generated/models/log_stream_request.py
new file mode 100644
index 00000000..10cb5ee8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/log_stream_request.py
@@ -0,0 +1,148 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+
+
+
+
+
+T = TypeVar("T", bound="LogStreamRequest")
+
+
+
+@_attrs_define
+class LogStreamRequest:
+ """ Stream request for live project logs. Pagination cursors and fixed end times are not supported.
+
+ Attributes:
+ resource (LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource): Resource
+ selectors for project log reads.
+ q (str | Unset): Optional log query using the same syntax as search and activity requests.
+ start_time (datetime.datetime | Unset): Start time.
+ limit (int | Unset): Maximum number of records to deliver on connect or reconnect before following new events.
+ Default: 100.
+ """
+
+ resource: LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource
+ q: str | Unset = UNSET
+ start_time: datetime.datetime | Unset = UNSET
+ limit: int | Unset = 100
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+ resource: dict[str, Any]
+ if isinstance(self.resource, LogFunctionRequestResource):
+ resource = self.resource.to_dict()
+ elif isinstance(self.resource, LogFrontendRequestResource):
+ resource = self.resource.to_dict()
+ else:
+ resource = self.resource.to_dict()
+
+
+ q = self.q
+
+ start_time: str | Unset = UNSET
+ if not isinstance(self.start_time, Unset):
+ start_time = self.start_time.isoformat()
+
+ limit = self.limit
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "resource": resource,
+ })
+ if q is not UNSET:
+ field_dict["q"] = q
+ if start_time is not UNSET:
+ field_dict["start_time"] = start_time
+ if limit is not UNSET:
+ field_dict["limit"] = limit
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.log_database_request_resource import LogDatabaseRequestResource
+ from ..models.log_frontend_request_resource import LogFrontendRequestResource
+ from ..models.log_function_request_resource import LogFunctionRequestResource
+ d = dict(src_dict)
+ def _parse_resource(data: object) -> LogDatabaseRequestResource | LogFrontendRequestResource | LogFunctionRequestResource:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_0 = LogFunctionRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_1 = LogFrontendRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_1
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_log_request_resource_type_2 = LogDatabaseRequestResource.from_dict(data)
+
+
+
+ return componentsschemas_log_request_resource_type_2
+
+ resource = _parse_resource(d.pop("resource"))
+
+
+ q = d.pop("q", UNSET)
+
+ _start_time = d.pop("start_time", UNSET)
+ start_time: datetime.datetime | Unset
+ if isinstance(_start_time, Unset):
+ start_time = UNSET
+ else:
+ start_time = datetime.datetime.fromisoformat(_start_time)
+
+
+
+
+ limit = d.pop("limit", UNSET)
+
+ log_stream_request = cls(
+ resource=resource,
+ q=q,
+ start_time=start_time,
+ limit=limit,
+ )
+
+ return log_stream_request
+
diff --git a/src/volcano_sdk/_generated/models/metric_usage_data.py b/src/volcano_sdk/_generated/models/metric_usage_data.py
new file mode 100644
index 00000000..2d859033
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/metric_usage_data.py
@@ -0,0 +1,146 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.usage_data_point import UsageDataPoint
+
+
+
+
+
+T = TypeVar("T", bound="MetricUsageData")
+
+
+
+@_attrs_define
+class MetricUsageData:
+ """ Usage data for one metric across totals, daily, and hourly windows.
+
+ Attributes:
+ metric (str): Metric name (for example, "Function & Frontend Invocations", "Frontend Requests",
+ "CodeBuild Build Seconds", "Bandwidth Ingress (Bytes)", "Bandwidth Egress (Bytes)",
+ "Bandwidth Total (Bytes)", or "Database Storage (Bytes)"). Byte-based metrics are
+ reported in bytes. "Bandwidth Total (Bytes)" is derived (ingress + egress) and
+ is not billed separately. "Database Storage (Bytes)" is a current observed gauge,
+ not a cumulative counter. It is the sum of the latest `pg_database_size` samples
+ exposed as `storage_bytes` by the project's database list.
+ total (int): Total usage for the current usage month
+ all_time (int): Lifetime cumulative usage across every month for this metric
+ daily (list[UsageDataPoint]): Last 30 days of daily usage points
+ hourly (list[UsageDataPoint]): Last 24 hours of hourly usage points
+ """
+
+ metric: str
+ total: int
+ all_time: int
+ daily: list[UsageDataPoint]
+ hourly: list[UsageDataPoint]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.usage_data_point import UsageDataPoint
+ metric = self.metric
+
+ total = self.total
+
+ all_time = self.all_time
+
+ daily = []
+ for daily_item_data in self.daily:
+ daily_item = daily_item_data.to_dict()
+ daily.append(daily_item)
+
+
+
+ hourly = []
+ for hourly_item_data in self.hourly:
+ hourly_item = hourly_item_data.to_dict()
+ hourly.append(hourly_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "metric": metric,
+ "total": total,
+ "all_time": all_time,
+ "daily": daily,
+ "hourly": hourly,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.usage_data_point import UsageDataPoint
+ d = dict(src_dict)
+ metric = d.pop("metric")
+
+ total = d.pop("total")
+
+ all_time = d.pop("all_time")
+
+ daily = []
+ _daily = d.pop("daily")
+ for daily_item_data in (_daily):
+ daily_item = UsageDataPoint.from_dict(daily_item_data)
+
+
+
+ daily.append(daily_item)
+
+
+ hourly = []
+ _hourly = d.pop("hourly")
+ for hourly_item_data in (_hourly):
+ hourly_item = UsageDataPoint.from_dict(hourly_item_data)
+
+
+
+ hourly.append(hourly_item)
+
+
+ metric_usage_data = cls(
+ metric=metric,
+ total=total,
+ all_time=all_time,
+ daily=daily,
+ hourly=hourly,
+ )
+
+
+ metric_usage_data.additional_properties = d
+ return metric_usage_data
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/o_auth_config.py b/src/volcano_sdk/_generated/models/o_auth_config.py
new file mode 100644
index 00000000..d7412d3f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/o_auth_config.py
@@ -0,0 +1,201 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.o_auth_config_provider import check_o_auth_config_provider
+from ..models.o_auth_config_provider import OAuthConfigProvider
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="OAuthConfig")
+
+
+
+@_attrs_define
+class OAuthConfig:
+ """
+ Attributes:
+ id (UUID | Unset):
+ provider (OAuthConfigProvider | Unset):
+ client_id (str | Unset): Example: 123456789.apps.googleusercontent.com.
+ client_secret (str | Unset): Masked in responses (shows only first/last 4 chars) Example: GOCS...****.
+ enabled (bool | Unset):
+ redirect_url (str | Unset): Example: https://yourapp.com/auth/callback.
+ scopes (list[str] | Unset): Example: ['openid', 'email', 'profile'].
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID | Unset = UNSET
+ provider: OAuthConfigProvider | Unset = UNSET
+ client_id: str | Unset = UNSET
+ client_secret: str | Unset = UNSET
+ enabled: bool | Unset = UNSET
+ redirect_url: str | Unset = UNSET
+ scopes: list[str] | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id: str | Unset = UNSET
+ if not isinstance(self.id, Unset):
+ id = str(self.id)
+
+ provider: str | Unset = UNSET
+ if not isinstance(self.provider, Unset):
+ provider = self.provider
+
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ enabled = self.enabled
+
+ redirect_url = self.redirect_url
+
+ scopes: list[str] | Unset = UNSET
+ if not isinstance(self.scopes, Unset):
+ scopes = self.scopes
+
+
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if id is not UNSET:
+ field_dict["id"] = id
+ if provider is not UNSET:
+ field_dict["provider"] = provider
+ if client_id is not UNSET:
+ field_dict["client_id"] = client_id
+ if client_secret is not UNSET:
+ field_dict["client_secret"] = client_secret
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if redirect_url is not UNSET:
+ field_dict["redirect_url"] = redirect_url
+ if scopes is not UNSET:
+ field_dict["scopes"] = scopes
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ _id = d.pop("id", UNSET)
+ id: UUID | Unset
+ if isinstance(_id, Unset):
+ id = UNSET
+ else:
+ id = UUID(_id)
+
+
+
+
+ _provider = d.pop("provider", UNSET)
+ provider: OAuthConfigProvider | Unset
+ if isinstance(_provider, Unset):
+ provider = UNSET
+ else:
+ provider = check_o_auth_config_provider(_provider)
+
+
+
+
+ client_id = d.pop("client_id", UNSET)
+
+ client_secret = d.pop("client_secret", UNSET)
+
+ enabled = d.pop("enabled", UNSET)
+
+ redirect_url = d.pop("redirect_url", UNSET)
+
+ scopes = cast(list[str], d.pop("scopes", UNSET))
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ o_auth_config = cls(
+ id=id,
+ provider=provider,
+ client_id=client_id,
+ client_secret=client_secret,
+ enabled=enabled,
+ redirect_url=redirect_url,
+ scopes=scopes,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ o_auth_config.additional_properties = d
+ return o_auth_config
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/o_auth_config_provider.py b/src/volcano_sdk/_generated/models/o_auth_config_provider.py
new file mode 100644
index 00000000..ab26843e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/o_auth_config_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+OAuthConfigProvider = Literal['apple', 'device', 'github', 'google', 'microsoft']
+
+O_AUTH_CONFIG_PROVIDER_VALUES: set[OAuthConfigProvider] = { 'apple', 'device', 'github', 'google', 'microsoft', }
+
+def check_o_auth_config_provider(value: str) -> OAuthConfigProvider:
+ if value in O_AUTH_CONFIG_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {O_AUTH_CONFIG_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/o_auth_error_response.py b/src/volcano_sdk/_generated/models/o_auth_error_response.py
new file mode 100644
index 00000000..0a47bece
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/o_auth_error_response.py
@@ -0,0 +1,86 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="OAuthErrorResponse")
+
+
+
+@_attrs_define
+class OAuthErrorResponse:
+ """
+ Attributes:
+ error (str):
+ error_description (str | Unset):
+ """
+
+ error: str
+ error_description: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ error = self.error
+
+ error_description = self.error_description
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "error": error,
+ })
+ if error_description is not UNSET:
+ field_dict["error_description"] = error_description
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ error = d.pop("error")
+
+ error_description = d.pop("error_description", UNSET)
+
+ o_auth_error_response = cls(
+ error=error,
+ error_description=error_description,
+ )
+
+
+ o_auth_error_response.additional_properties = d
+ return o_auth_error_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_auth_users.py b/src/volcano_sdk/_generated/models/paginated_auth_users.py
new file mode 100644
index 00000000..3d2d01c3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_auth_users.py
@@ -0,0 +1,136 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.auth_user import AuthUser
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedAuthUsers")
+
+
+
+@_attrs_define
+class PaginatedAuthUsers:
+ """
+ Attributes:
+ data (list[AuthUser]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (only present if has_more is true)
+ """
+
+ data: list[AuthUser]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.auth_user import AuthUser
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.auth_user import AuthUser
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = AuthUser.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ paginated_auth_users = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ )
+
+
+ paginated_auth_users.additional_properties = d
+ return paginated_auth_users
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_databases.py b/src/volcano_sdk/_generated/models/paginated_databases.py
new file mode 100644
index 00000000..8876b74d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_databases.py
@@ -0,0 +1,155 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.database import Database
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedDatabases")
+
+
+
+@_attrs_define
+class PaginatedDatabases:
+ """
+ Attributes:
+ data (list[Database]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (only present if has_more is true)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ """
+
+ data: list[Database]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.database import Database
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.database import Database
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = Database.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ paginated_databases = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ paginated_databases.additional_properties = d
+ return paginated_databases
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_frontend_deployments.py b/src/volcano_sdk/_generated/models/paginated_frontend_deployments.py
new file mode 100644
index 00000000..14997a74
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_frontend_deployments.py
@@ -0,0 +1,136 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.frontend_deployment import FrontendDeployment
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedFrontendDeployments")
+
+
+
+@_attrs_define
+class PaginatedFrontendDeployments:
+ """
+ Attributes:
+ data (list[FrontendDeployment]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (only present if has_more is true)
+ """
+
+ data: list[FrontendDeployment]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend_deployment import FrontendDeployment
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend_deployment import FrontendDeployment
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = FrontendDeployment.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ paginated_frontend_deployments = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ )
+
+
+ paginated_frontend_deployments.additional_properties = d
+ return paginated_frontend_deployments
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_frontends.py b/src/volcano_sdk/_generated/models/paginated_frontends.py
new file mode 100644
index 00000000..3530c0ae
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_frontends.py
@@ -0,0 +1,155 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.frontend import Frontend
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedFrontends")
+
+
+
+@_attrs_define
+class PaginatedFrontends:
+ """
+ Attributes:
+ data (list[Frontend]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ """
+
+ data: list[Frontend]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend import Frontend
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend import Frontend
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = Frontend.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ paginated_frontends = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ paginated_frontends.additional_properties = d
+ return paginated_frontends
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_function_deployments.py b/src/volcano_sdk/_generated/models/paginated_function_deployments.py
new file mode 100644
index 00000000..262f102a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_function_deployments.py
@@ -0,0 +1,136 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.function_deployment import FunctionDeployment
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedFunctionDeployments")
+
+
+
+@_attrs_define
+class PaginatedFunctionDeployments:
+ """
+ Attributes:
+ data (list[FunctionDeployment]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (only present if has_more is true)
+ """
+
+ data: list[FunctionDeployment]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.function_deployment import FunctionDeployment
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.function_deployment import FunctionDeployment
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = FunctionDeployment.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ paginated_function_deployments = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ )
+
+
+ paginated_function_deployments.additional_properties = d
+ return paginated_function_deployments
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_functions.py b/src/volcano_sdk/_generated/models/paginated_functions.py
new file mode 100644
index 00000000..3acf3d7d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_functions.py
@@ -0,0 +1,155 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.function import Function
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedFunctions")
+
+
+
+@_attrs_define
+class PaginatedFunctions:
+ """
+ Attributes:
+ data (list[Function]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (only present if has_more is true)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ """
+
+ data: list[Function]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.function import Function
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.function import Function
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = Function.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ paginated_functions = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ paginated_functions.additional_properties = d
+ return paginated_functions
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_project_custom_domains.py b/src/volcano_sdk/_generated/models/paginated_project_custom_domains.py
new file mode 100644
index 00000000..226aa479
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_project_custom_domains.py
@@ -0,0 +1,136 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_frontend_custom_domain import ProjectFrontendCustomDomain
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedProjectCustomDomains")
+
+
+
+@_attrs_define
+class PaginatedProjectCustomDomains:
+ """
+ Attributes:
+ data (list[ProjectFrontendCustomDomain]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (only present if has_more is true)
+ """
+
+ data: list[ProjectFrontendCustomDomain]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_frontend_custom_domain import ProjectFrontendCustomDomain
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_frontend_custom_domain import ProjectFrontendCustomDomain
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = ProjectFrontendCustomDomain.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ paginated_project_custom_domains = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ )
+
+
+ paginated_project_custom_domains.additional_properties = d
+ return paginated_project_custom_domains
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_project_deployments.py b/src/volcano_sdk/_generated/models/paginated_project_deployments.py
new file mode 100644
index 00000000..8a54922a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_project_deployments.py
@@ -0,0 +1,159 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_deployment import ProjectDeployment
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedProjectDeployments")
+
+
+
+@_attrs_define
+class PaginatedProjectDeployments:
+ """
+ Attributes:
+ data (list[ProjectDeployment]):
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ page (int | Unset): Current page number (1-indexed). Offset pagination only — omitted in
+ cursor mode, where position comes from the cursor and there is no page
+ number to report. Required-and-1-indexed would otherwise force a `0`
+ onto every cursor response.
+ next_ (str | Unset): URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ """
+
+ data: list[ProjectDeployment]
+ limit: int
+ total: int
+ has_more: bool
+ page: int | Unset = UNSET
+ next_: str | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_deployment import ProjectDeployment
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ page = self.page
+
+ next_ = self.next_
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if page is not UNSET:
+ field_dict["page"] = page
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_deployment import ProjectDeployment
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = ProjectDeployment.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ page = d.pop("page", UNSET)
+
+ next_ = d.pop("next", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ paginated_project_deployments = cls(
+ data=data,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ page=page,
+ next_=next_,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ paginated_project_deployments.additional_properties = d
+ return paginated_project_deployments
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_projects.py b/src/volcano_sdk/_generated/models/paginated_projects.py
new file mode 100644
index 00000000..25ef9ea9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_projects.py
@@ -0,0 +1,218 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.paginated_projects_status import check_paginated_projects_status
+from ..models.paginated_projects_status import PaginatedProjectsStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.project import Project
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedProjects")
+
+
+
+@_attrs_define
+class PaginatedProjects:
+ """
+ Attributes:
+ data (list[Project]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ status (PaginatedProjectsStatus | Unset): Latest project variable propagation status.
+ current_sync_id (UUID | Unset): Identifier of the latest variable propagation sync.
+ provisioning_started_at (datetime.datetime | Unset): Timestamp when the current variable propagation phase
+ started.
+ """
+
+ data: list[Project]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ status: PaginatedProjectsStatus | Unset = UNSET
+ current_sync_id: UUID | Unset = UNSET
+ provisioning_started_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project import Project
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+ status: str | Unset = UNSET
+ if not isinstance(self.status, Unset):
+ status = self.status
+
+
+ current_sync_id: str | Unset = UNSET
+ if not isinstance(self.current_sync_id, Unset):
+ current_sync_id = str(self.current_sync_id)
+
+ provisioning_started_at: str | Unset = UNSET
+ if not isinstance(self.provisioning_started_at, Unset):
+ provisioning_started_at = self.provisioning_started_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+ if status is not UNSET:
+ field_dict["status"] = status
+ if current_sync_id is not UNSET:
+ field_dict["current_sync_id"] = current_sync_id
+ if provisioning_started_at is not UNSET:
+ field_dict["provisioning_started_at"] = provisioning_started_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project import Project
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = Project.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ _status = d.pop("status", UNSET)
+ status: PaginatedProjectsStatus | Unset
+ if isinstance(_status, Unset):
+ status = UNSET
+ else:
+ status = check_paginated_projects_status(_status)
+
+
+
+
+ _current_sync_id = d.pop("current_sync_id", UNSET)
+ current_sync_id: UUID | Unset
+ if isinstance(_current_sync_id, Unset):
+ current_sync_id = UNSET
+ else:
+ current_sync_id = UUID(_current_sync_id)
+
+
+
+
+ _provisioning_started_at = d.pop("provisioning_started_at", UNSET)
+ provisioning_started_at: datetime.datetime | Unset
+ if isinstance(_provisioning_started_at, Unset):
+ provisioning_started_at = UNSET
+ else:
+ provisioning_started_at = datetime.datetime.fromisoformat(_provisioning_started_at)
+
+
+
+
+ paginated_projects = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ status=status,
+ current_sync_id=current_sync_id,
+ provisioning_started_at=provisioning_started_at,
+ )
+
+
+ paginated_projects.additional_properties = d
+ return paginated_projects
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_projects_status.py b/src/volcano_sdk/_generated/models/paginated_projects_status.py
new file mode 100644
index 00000000..d21b5961
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_projects_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+PaginatedProjectsStatus = Literal['active', 'failed', 'provisioning']
+
+PAGINATED_PROJECTS_STATUS_VALUES: set[PaginatedProjectsStatus] = { 'active', 'failed', 'provisioning', }
+
+def check_paginated_projects_status(value: str) -> PaginatedProjectsStatus:
+ if value in PAGINATED_PROJECTS_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PAGINATED_PROJECTS_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/paginated_service_keys.py b/src/volcano_sdk/_generated/models/paginated_service_keys.py
new file mode 100644
index 00000000..98f19d37
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_service_keys.py
@@ -0,0 +1,155 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.service_key import ServiceKey
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedServiceKeys")
+
+
+
+@_attrs_define
+class PaginatedServiceKeys:
+ """
+ Attributes:
+ data (list[ServiceKey]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (offset pagination only; present if has_more is true)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ """
+
+ data: list[ServiceKey]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.service_key import ServiceKey
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.service_key import ServiceKey
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = ServiceKey.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ paginated_service_keys = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ paginated_service_keys.additional_properties = d
+ return paginated_service_keys
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_storage_buckets.py b/src/volcano_sdk/_generated/models/paginated_storage_buckets.py
new file mode 100644
index 00000000..388770e2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_storage_buckets.py
@@ -0,0 +1,140 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.storage_bucket import StorageBucket
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedStorageBuckets")
+
+
+
+@_attrs_define
+class PaginatedStorageBuckets:
+ """ Cursor-paginated storage buckets (returned only when cursor pagination is requested).
+
+ Attributes:
+ data (list[StorageBucket]):
+ limit (int): Number of items per page
+ has_more (bool): Whether a next page exists
+ total (int | Unset): Total number of items matching the query
+ next_cursor (str | Unset): Opaque cursor for the next page (present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (present when a previous page exists). Send as
+ `ending_before`.
+ """
+
+ data: list[StorageBucket]
+ limit: int
+ has_more: bool
+ total: int | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.storage_bucket import StorageBucket
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ limit = self.limit
+
+ has_more = self.has_more
+
+ total = self.total
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "limit": limit,
+ "has_more": has_more,
+ })
+ if total is not UNSET:
+ field_dict["total"] = total
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.storage_bucket import StorageBucket
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = StorageBucket.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ limit = d.pop("limit")
+
+ has_more = d.pop("has_more")
+
+ total = d.pop("total", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ paginated_storage_buckets = cls(
+ data=data,
+ limit=limit,
+ has_more=has_more,
+ total=total,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ paginated_storage_buckets.additional_properties = d
+ return paginated_storage_buckets
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/paginated_variables.py b/src/volcano_sdk/_generated/models/paginated_variables.py
new file mode 100644
index 00000000..4c476f0e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/paginated_variables.py
@@ -0,0 +1,155 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.variable import Variable
+
+
+
+
+
+T = TypeVar("T", bound="PaginatedVariables")
+
+
+
+@_attrs_define
+class PaginatedVariables:
+ """
+ Attributes:
+ data (list[Variable]):
+ page (int): Current page number (1-indexed)
+ limit (int): Number of items per page
+ total (int): Total number of items across all pages
+ has_more (bool): Whether there are more pages available
+ next_ (str | Unset): URL path to next page (only present if has_more is true)
+ next_cursor (str | Unset): Opaque cursor for the next page (cursor pagination only; present if has_more is true)
+ prev_cursor (str | Unset): Opaque cursor for the previous page (cursor pagination only; present when a previous
+ page exists). Send as `ending_before`.
+ """
+
+ data: list[Variable]
+ page: int
+ limit: int
+ total: int
+ has_more: bool
+ next_: str | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ prev_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.variable import Variable
+ data = []
+ for data_item_data in self.data:
+ data_item = data_item_data.to_dict()
+ data.append(data_item)
+
+
+
+ page = self.page
+
+ limit = self.limit
+
+ total = self.total
+
+ has_more = self.has_more
+
+ next_ = self.next_
+
+ next_cursor = self.next_cursor
+
+ prev_cursor = self.prev_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "data": data,
+ "page": page,
+ "limit": limit,
+ "total": total,
+ "has_more": has_more,
+ })
+ if next_ is not UNSET:
+ field_dict["next"] = next_
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+ if prev_cursor is not UNSET:
+ field_dict["prev_cursor"] = prev_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.variable import Variable
+ d = dict(src_dict)
+ data = []
+ _data = d.pop("data")
+ for data_item_data in (_data):
+ data_item = Variable.from_dict(data_item_data)
+
+
+
+ data.append(data_item)
+
+
+ page = d.pop("page")
+
+ limit = d.pop("limit")
+
+ total = d.pop("total")
+
+ has_more = d.pop("has_more")
+
+ next_ = d.pop("next", UNSET)
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ prev_cursor = d.pop("prev_cursor", UNSET)
+
+ paginated_variables = cls(
+ data=data,
+ page=page,
+ limit=limit,
+ total=total,
+ has_more=has_more,
+ next_=next_,
+ next_cursor=next_cursor,
+ prev_cursor=prev_cursor,
+ )
+
+
+ paginated_variables.additional_properties = d
+ return paginated_variables
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/platform_exchange_response.py b/src/volcano_sdk/_generated/models/platform_exchange_response.py
new file mode 100644
index 00000000..98af8704
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/platform_exchange_response.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="PlatformExchangeResponse")
+
+
+
+@_attrs_define
+class PlatformExchangeResponse:
+ """
+ Attributes:
+ token (str):
+ user_id (str):
+ token_id (UUID):
+ expires_at (datetime.datetime):
+ """
+
+ token: str
+ user_id: str
+ token_id: UUID
+ expires_at: datetime.datetime
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ token = self.token
+
+ user_id = self.user_id
+
+ token_id = str(self.token_id)
+
+ expires_at = self.expires_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "token": token,
+ "user_id": user_id,
+ "token_id": token_id,
+ "expires_at": expires_at,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ token = d.pop("token")
+
+ user_id = d.pop("user_id")
+
+ token_id = UUID(d.pop("token_id"))
+
+
+
+
+ expires_at = datetime.datetime.fromisoformat(d.pop("expires_at"))
+
+
+
+
+ platform_exchange_response = cls(
+ token=token,
+ user_id=user_id,
+ token_id=token_id,
+ expires_at=expires_at,
+ )
+
+
+ platform_exchange_response.additional_properties = d
+ return platform_exchange_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project.py b/src/volcano_sdk/_generated/models/project.py
new file mode 100644
index 00000000..74a8bdbf
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project.py
@@ -0,0 +1,210 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_plan import check_project_plan
+from ..models.project_plan import ProjectPlan
+from ..models.project_status import check_project_status
+from ..models.project_status import ProjectStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="Project")
+
+
+
+@_attrs_define
+class Project:
+ """
+ Attributes:
+ id (UUID):
+ name (str):
+ status (ProjectStatus):
+ all_regions (bool): Region policy for function deployment.
+ - `true`: deploy functions to all configured platform regions
+ - `false`: deploy only to `selected_regions`
+ selected_regions (list[str]): Effective region set for this project (normalized and deduplicated)
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ plan (ProjectPlan | Unset): Platform plan applied to the project when available
+ aws_application_name (str | Unset):
+ last_invoked_at (datetime.datetime | Unset): Most recent activity timestamp across project resources
+ logo_url (str | Unset): Relative API path that serves the project logo when one has been
+ uploaded. The path is versioned with a `?v=` cache-busting query
+ param that changes on each upload. Absent when the project has no
+ logo. The logo image is stored in the project's storage folder.
+ Example: /projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/logo?v=1718524800.
+ """
+
+ id: UUID
+ name: str
+ status: ProjectStatus
+ all_regions: bool
+ selected_regions: list[str]
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ plan: ProjectPlan | Unset = UNSET
+ aws_application_name: str | Unset = UNSET
+ last_invoked_at: datetime.datetime | Unset = UNSET
+ logo_url: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ name = self.name
+
+ status: str = self.status
+
+ all_regions = self.all_regions
+
+ selected_regions = self.selected_regions
+
+
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ plan: str | Unset = UNSET
+ if not isinstance(self.plan, Unset):
+ plan = self.plan
+
+
+ aws_application_name = self.aws_application_name
+
+ last_invoked_at: str | Unset = UNSET
+ if not isinstance(self.last_invoked_at, Unset):
+ last_invoked_at = self.last_invoked_at.isoformat()
+
+ logo_url = self.logo_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ "status": status,
+ "all_regions": all_regions,
+ "selected_regions": selected_regions,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if plan is not UNSET:
+ field_dict["plan"] = plan
+ if aws_application_name is not UNSET:
+ field_dict["aws_application_name"] = aws_application_name
+ if last_invoked_at is not UNSET:
+ field_dict["last_invoked_at"] = last_invoked_at
+ if logo_url is not UNSET:
+ field_dict["logo_url"] = logo_url
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ status = check_project_status(d.pop("status"))
+
+
+
+
+ all_regions = d.pop("all_regions")
+
+ selected_regions = cast(list[str], d.pop("selected_regions"))
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ _plan = d.pop("plan", UNSET)
+ plan: ProjectPlan | Unset
+ if isinstance(_plan, Unset):
+ plan = UNSET
+ else:
+ plan = check_project_plan(_plan)
+
+
+
+
+ aws_application_name = d.pop("aws_application_name", UNSET)
+
+ _last_invoked_at = d.pop("last_invoked_at", UNSET)
+ last_invoked_at: datetime.datetime | Unset
+ if isinstance(_last_invoked_at, Unset):
+ last_invoked_at = UNSET
+ else:
+ last_invoked_at = datetime.datetime.fromisoformat(_last_invoked_at)
+
+
+
+
+ logo_url = d.pop("logo_url", UNSET)
+
+ project = cls(
+ id=id,
+ name=name,
+ status=status,
+ all_regions=all_regions,
+ selected_regions=selected_regions,
+ created_at=created_at,
+ updated_at=updated_at,
+ plan=plan,
+ aws_application_name=aws_application_name,
+ last_invoked_at=last_invoked_at,
+ logo_url=logo_url,
+ )
+
+
+ project.additional_properties = d
+ return project
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config.py b/src/volcano_sdk/_generated/models/project_config.py
new file mode 100644
index 00000000..39fce18b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config.py
@@ -0,0 +1,288 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_version import check_project_config_version
+from ..models.project_config_version import ProjectConfigVersion
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_auth import ProjectConfigAuth
+ from ..models.project_config_bucket import ProjectConfigBucket
+ from ..models.project_config_database import ProjectConfigDatabase
+ from ..models.project_config_frontend import ProjectConfigFrontend
+ from ..models.project_config_function import ProjectConfigFunction
+ from ..models.project_config_project import ProjectConfigProject
+ from ..models.project_config_realtime import ProjectConfigRealtime
+ from ..models.project_config_variable import ProjectConfigVariable
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfig")
+
+
+
+@_attrs_define
+class ProjectConfig:
+ """ Declarative project configuration manifest (the JSON form of
+ volcano-config.yaml). Omitted sections are left untouched. Within
+ declared entries, omitted optional fields keep their current server
+ values (patch semantics). Declared collection keys are fully synced to
+ the manifest: `variables`, `buckets[].policies`, `auth.providers.oauth`,
+ `auth.email.templates`, and `functions[].schedulers` are reconciled to
+ exactly match, deleting resources absent from the manifest. Functions,
+ frontends, databases, and buckets are never created or deleted through
+ this manifest; entries referencing resources that do not exist are
+ skipped and reported.
+
+ Attributes:
+ version (ProjectConfigVersion): Manifest schema version. Must be 1.
+ project (ProjectConfigProject | Unset): Project-level settings. `name` renames the project.
+ databases (list[ProjectConfigDatabase] | Unset):
+ variables (list[ProjectConfigVariable] | Unset): Fully synced when declared - variables absent from this list
+ are deleted.
+ buckets (list[ProjectConfigBucket] | Unset):
+ realtime (ProjectConfigRealtime | Unset):
+ auth (ProjectConfigAuth | Unset): Authentication settings, grouped like the dashboard auth-settings tabs.
+ functions (list[ProjectConfigFunction] | Unset):
+ frontends (list[ProjectConfigFrontend] | Unset):
+ """
+
+ version: ProjectConfigVersion
+ project: ProjectConfigProject | Unset = UNSET
+ databases: list[ProjectConfigDatabase] | Unset = UNSET
+ variables: list[ProjectConfigVariable] | Unset = UNSET
+ buckets: list[ProjectConfigBucket] | Unset = UNSET
+ realtime: ProjectConfigRealtime | Unset = UNSET
+ auth: ProjectConfigAuth | Unset = UNSET
+ functions: list[ProjectConfigFunction] | Unset = UNSET
+ frontends: list[ProjectConfigFrontend] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_auth import ProjectConfigAuth
+ from ..models.project_config_bucket import ProjectConfigBucket
+ from ..models.project_config_database import ProjectConfigDatabase
+ from ..models.project_config_frontend import ProjectConfigFrontend
+ from ..models.project_config_function import ProjectConfigFunction
+ from ..models.project_config_project import ProjectConfigProject
+ from ..models.project_config_realtime import ProjectConfigRealtime
+ from ..models.project_config_variable import ProjectConfigVariable
+ version: int = self.version
+
+ project: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.project, Unset):
+ project = self.project.to_dict()
+
+ databases: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.databases, Unset):
+ databases = []
+ for databases_item_data in self.databases:
+ databases_item = databases_item_data.to_dict()
+ databases.append(databases_item)
+
+
+
+ variables: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.variables, Unset):
+ variables = []
+ for variables_item_data in self.variables:
+ variables_item = variables_item_data.to_dict()
+ variables.append(variables_item)
+
+
+
+ buckets: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.buckets, Unset):
+ buckets = []
+ for buckets_item_data in self.buckets:
+ buckets_item = buckets_item_data.to_dict()
+ buckets.append(buckets_item)
+
+
+
+ realtime: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.realtime, Unset):
+ realtime = self.realtime.to_dict()
+
+ auth: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.auth, Unset):
+ auth = self.auth.to_dict()
+
+ functions: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.functions, Unset):
+ functions = []
+ for functions_item_data in self.functions:
+ functions_item = functions_item_data.to_dict()
+ functions.append(functions_item)
+
+
+
+ frontends: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.frontends, Unset):
+ frontends = []
+ for frontends_item_data in self.frontends:
+ frontends_item = frontends_item_data.to_dict()
+ frontends.append(frontends_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "version": version,
+ })
+ if project is not UNSET:
+ field_dict["project"] = project
+ if databases is not UNSET:
+ field_dict["databases"] = databases
+ if variables is not UNSET:
+ field_dict["variables"] = variables
+ if buckets is not UNSET:
+ field_dict["buckets"] = buckets
+ if realtime is not UNSET:
+ field_dict["realtime"] = realtime
+ if auth is not UNSET:
+ field_dict["auth"] = auth
+ if functions is not UNSET:
+ field_dict["functions"] = functions
+ if frontends is not UNSET:
+ field_dict["frontends"] = frontends
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_auth import ProjectConfigAuth
+ from ..models.project_config_bucket import ProjectConfigBucket
+ from ..models.project_config_database import ProjectConfigDatabase
+ from ..models.project_config_frontend import ProjectConfigFrontend
+ from ..models.project_config_function import ProjectConfigFunction
+ from ..models.project_config_project import ProjectConfigProject
+ from ..models.project_config_realtime import ProjectConfigRealtime
+ from ..models.project_config_variable import ProjectConfigVariable
+ d = dict(src_dict)
+ version = check_project_config_version(d.pop("version"))
+
+
+
+
+ _project = d.pop("project", UNSET)
+ project: ProjectConfigProject | Unset
+ if isinstance(_project, Unset):
+ project = UNSET
+ else:
+ project = ProjectConfigProject.from_dict(_project)
+
+
+
+
+ _databases = d.pop("databases", UNSET)
+ databases: list[ProjectConfigDatabase] | Unset = UNSET
+ if _databases is not UNSET:
+ databases = []
+ for databases_item_data in _databases:
+ databases_item = ProjectConfigDatabase.from_dict(databases_item_data)
+
+
+
+ databases.append(databases_item)
+
+
+ _variables = d.pop("variables", UNSET)
+ variables: list[ProjectConfigVariable] | Unset = UNSET
+ if _variables is not UNSET:
+ variables = []
+ for variables_item_data in _variables:
+ variables_item = ProjectConfigVariable.from_dict(variables_item_data)
+
+
+
+ variables.append(variables_item)
+
+
+ _buckets = d.pop("buckets", UNSET)
+ buckets: list[ProjectConfigBucket] | Unset = UNSET
+ if _buckets is not UNSET:
+ buckets = []
+ for buckets_item_data in _buckets:
+ buckets_item = ProjectConfigBucket.from_dict(buckets_item_data)
+
+
+
+ buckets.append(buckets_item)
+
+
+ _realtime = d.pop("realtime", UNSET)
+ realtime: ProjectConfigRealtime | Unset
+ if isinstance(_realtime, Unset):
+ realtime = UNSET
+ else:
+ realtime = ProjectConfigRealtime.from_dict(_realtime)
+
+
+
+
+ _auth = d.pop("auth", UNSET)
+ auth: ProjectConfigAuth | Unset
+ if isinstance(_auth, Unset):
+ auth = UNSET
+ else:
+ auth = ProjectConfigAuth.from_dict(_auth)
+
+
+
+
+ _functions = d.pop("functions", UNSET)
+ functions: list[ProjectConfigFunction] | Unset = UNSET
+ if _functions is not UNSET:
+ functions = []
+ for functions_item_data in _functions:
+ functions_item = ProjectConfigFunction.from_dict(functions_item_data)
+
+
+
+ functions.append(functions_item)
+
+
+ _frontends = d.pop("frontends", UNSET)
+ frontends: list[ProjectConfigFrontend] | Unset = UNSET
+ if _frontends is not UNSET:
+ frontends = []
+ for frontends_item_data in _frontends:
+ frontends_item = ProjectConfigFrontend.from_dict(frontends_item_data)
+
+
+
+ frontends.append(frontends_item)
+
+
+ project_config = cls(
+ version=version,
+ project=project,
+ databases=databases,
+ variables=variables,
+ buckets=buckets,
+ realtime=realtime,
+ auth=auth,
+ functions=functions,
+ frontends=frontends,
+ )
+
+ return project_config
+
diff --git a/src/volcano_sdk/_generated/models/project_config_apply_result.py b/src/volcano_sdk/_generated/models/project_config_apply_result.py
new file mode 100644
index 00000000..9d6c5fb1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_apply_result.py
@@ -0,0 +1,170 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_apply_result_entry import ProjectConfigApplyResultEntry
+ from ..models.project_config_apply_summary import ProjectConfigApplySummary
+ from ..models.project_config_missing_resource import ProjectConfigMissingResource
+ from ..models.project_config_skipped_resource import ProjectConfigSkippedResource
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigApplyResult")
+
+
+
+@_attrs_define
+class ProjectConfigApplyResult:
+ """ Per-resource report for a project config apply (or dry run).
+
+ Attributes:
+ results (list[ProjectConfigApplyResultEntry]):
+ skipped (list[ProjectConfigSkippedResource]): Manifest entries referencing functions, frontends, databases, or
+ buckets that do not exist. Their configuration was not applied;
+ deploy/create the resource first, then re-apply.
+ missing (list[ProjectConfigMissingResource]): Existing functions, frontends, databases, or buckets that have no
+ entry in the corresponding declared manifest section.
+ summary (ProjectConfigApplySummary):
+ dry_run (bool | Unset): True when the request was a dry run and no changes were made.
+ """
+
+ results: list[ProjectConfigApplyResultEntry]
+ skipped: list[ProjectConfigSkippedResource]
+ missing: list[ProjectConfigMissingResource]
+ summary: ProjectConfigApplySummary
+ dry_run: bool | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_apply_result_entry import ProjectConfigApplyResultEntry
+ from ..models.project_config_apply_summary import ProjectConfigApplySummary
+ from ..models.project_config_missing_resource import ProjectConfigMissingResource
+ from ..models.project_config_skipped_resource import ProjectConfigSkippedResource
+ results = []
+ for results_item_data in self.results:
+ results_item = results_item_data.to_dict()
+ results.append(results_item)
+
+
+
+ skipped = []
+ for skipped_item_data in self.skipped:
+ skipped_item = skipped_item_data.to_dict()
+ skipped.append(skipped_item)
+
+
+
+ missing = []
+ for missing_item_data in self.missing:
+ missing_item = missing_item_data.to_dict()
+ missing.append(missing_item)
+
+
+
+ summary = self.summary.to_dict()
+
+ dry_run = self.dry_run
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "results": results,
+ "skipped": skipped,
+ "missing": missing,
+ "summary": summary,
+ })
+ if dry_run is not UNSET:
+ field_dict["dry_run"] = dry_run
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_apply_result_entry import ProjectConfigApplyResultEntry
+ from ..models.project_config_apply_summary import ProjectConfigApplySummary
+ from ..models.project_config_missing_resource import ProjectConfigMissingResource
+ from ..models.project_config_skipped_resource import ProjectConfigSkippedResource
+ d = dict(src_dict)
+ results = []
+ _results = d.pop("results")
+ for results_item_data in (_results):
+ results_item = ProjectConfigApplyResultEntry.from_dict(results_item_data)
+
+
+
+ results.append(results_item)
+
+
+ skipped = []
+ _skipped = d.pop("skipped")
+ for skipped_item_data in (_skipped):
+ skipped_item = ProjectConfigSkippedResource.from_dict(skipped_item_data)
+
+
+
+ skipped.append(skipped_item)
+
+
+ missing = []
+ _missing = d.pop("missing")
+ for missing_item_data in (_missing):
+ missing_item = ProjectConfigMissingResource.from_dict(missing_item_data)
+
+
+
+ missing.append(missing_item)
+
+
+ summary = ProjectConfigApplySummary.from_dict(d.pop("summary"))
+
+
+
+
+ dry_run = d.pop("dry_run", UNSET)
+
+ project_config_apply_result = cls(
+ results=results,
+ skipped=skipped,
+ missing=missing,
+ summary=summary,
+ dry_run=dry_run,
+ )
+
+
+ project_config_apply_result.additional_properties = d
+ return project_config_apply_result
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_apply_result_entry.py b/src/volcano_sdk/_generated/models/project_config_apply_result_entry.py
new file mode 100644
index 00000000..34360379
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_apply_result_entry.py
@@ -0,0 +1,118 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_apply_result_entry_action import check_project_config_apply_result_entry_action
+from ..models.project_config_apply_result_entry_action import ProjectConfigApplyResultEntryAction
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigApplyResultEntry")
+
+
+
+@_attrs_define
+class ProjectConfigApplyResultEntry:
+ """
+ Attributes:
+ section (str): Manifest section the entry belongs to (e.g. variables, buckets, auth.providers.oauth).
+ action (ProjectConfigApplyResultEntryAction):
+ name (str | Unset): Resource name or key within the section. Empty for singleton sections.
+ error (str | Unset): Error detail when action is `error`.
+ notice (str | Unset): Optional operational note (e.g. disabling realtime drops active connections).
+ """
+
+ section: str
+ action: ProjectConfigApplyResultEntryAction
+ name: str | Unset = UNSET
+ error: str | Unset = UNSET
+ notice: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ section = self.section
+
+ action: str = self.action
+
+ name = self.name
+
+ error = self.error
+
+ notice = self.notice
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "section": section,
+ "action": action,
+ })
+ if name is not UNSET:
+ field_dict["name"] = name
+ if error is not UNSET:
+ field_dict["error"] = error
+ if notice is not UNSET:
+ field_dict["notice"] = notice
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ section = d.pop("section")
+
+ action = check_project_config_apply_result_entry_action(d.pop("action"))
+
+
+
+
+ name = d.pop("name", UNSET)
+
+ error = d.pop("error", UNSET)
+
+ notice = d.pop("notice", UNSET)
+
+ project_config_apply_result_entry = cls(
+ section=section,
+ action=action,
+ name=name,
+ error=error,
+ notice=notice,
+ )
+
+
+ project_config_apply_result_entry.additional_properties = d
+ return project_config_apply_result_entry
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_apply_result_entry_action.py b/src/volcano_sdk/_generated/models/project_config_apply_result_entry_action.py
new file mode 100644
index 00000000..c241435f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_apply_result_entry_action.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigApplyResultEntryAction = Literal['created', 'deleted', 'error', 'unchanged', 'updated']
+
+PROJECT_CONFIG_APPLY_RESULT_ENTRY_ACTION_VALUES: set[ProjectConfigApplyResultEntryAction] = { 'created', 'deleted', 'error', 'unchanged', 'updated', }
+
+def check_project_config_apply_result_entry_action(value: str) -> ProjectConfigApplyResultEntryAction:
+ if value in PROJECT_CONFIG_APPLY_RESULT_ENTRY_ACTION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_APPLY_RESULT_ENTRY_ACTION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_apply_summary.py b/src/volcano_sdk/_generated/models/project_config_apply_summary.py
new file mode 100644
index 00000000..717b80d3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_apply_summary.py
@@ -0,0 +1,124 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigApplySummary")
+
+
+
+@_attrs_define
+class ProjectConfigApplySummary:
+ """
+ Attributes:
+ created (int):
+ updated (int):
+ deleted (int):
+ unchanged (int):
+ errors (int):
+ skipped (int):
+ missing (int):
+ """
+
+ created: int
+ updated: int
+ deleted: int
+ unchanged: int
+ errors: int
+ skipped: int
+ missing: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ created = self.created
+
+ updated = self.updated
+
+ deleted = self.deleted
+
+ unchanged = self.unchanged
+
+ errors = self.errors
+
+ skipped = self.skipped
+
+ missing = self.missing
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "created": created,
+ "updated": updated,
+ "deleted": deleted,
+ "unchanged": unchanged,
+ "errors": errors,
+ "skipped": skipped,
+ "missing": missing,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ created = d.pop("created")
+
+ updated = d.pop("updated")
+
+ deleted = d.pop("deleted")
+
+ unchanged = d.pop("unchanged")
+
+ errors = d.pop("errors")
+
+ skipped = d.pop("skipped")
+
+ missing = d.pop("missing")
+
+ project_config_apply_summary = cls(
+ created=created,
+ updated=updated,
+ deleted=deleted,
+ unchanged=unchanged,
+ errors=errors,
+ skipped=skipped,
+ missing=missing,
+ )
+
+
+ project_config_apply_summary.additional_properties = d
+ return project_config_apply_summary
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_auth.py b/src/volcano_sdk/_generated/models/project_config_auth.py
new file mode 100644
index 00000000..ce6b49d7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth.py
@@ -0,0 +1,296 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_auth_cors import ProjectConfigAuthCORS
+ from ..models.project_config_auth_email import ProjectConfigAuthEmail
+ from ..models.project_config_auth_email_verification import ProjectConfigAuthEmailVerification
+ from ..models.project_config_auth_managed_pages import ProjectConfigAuthManagedPages
+ from ..models.project_config_auth_password import ProjectConfigAuthPassword
+ from ..models.project_config_auth_password_reset import ProjectConfigAuthPasswordReset
+ from ..models.project_config_auth_providers import ProjectConfigAuthProviders
+ from ..models.project_config_auth_rate_limits import ProjectConfigAuthRateLimits
+ from ..models.project_config_auth_sessions import ProjectConfigAuthSessions
+ from ..models.project_config_auth_signup import ProjectConfigAuthSignup
+ from ..models.project_config_auth_tokens import ProjectConfigAuthTokens
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuth")
+
+
+
+@_attrs_define
+class ProjectConfigAuth:
+ """ Authentication settings, grouped like the dashboard auth-settings tabs.
+
+ Attributes:
+ tokens (ProjectConfigAuthTokens | Unset): Token lifetimes in seconds.
+ sessions (ProjectConfigAuthSessions | Unset):
+ signup (ProjectConfigAuthSignup | Unset):
+ rate_limits (ProjectConfigAuthRateLimits | Unset): Rate limits per hour.
+ password (ProjectConfigAuthPassword | Unset):
+ password_reset (ProjectConfigAuthPasswordReset | Unset):
+ email_verification (ProjectConfigAuthEmailVerification | Unset):
+ cors (ProjectConfigAuthCORS | Unset):
+ providers (ProjectConfigAuthProviders | Unset):
+ email (ProjectConfigAuthEmail | Unset):
+ managed_pages (ProjectConfigAuthManagedPages | Unset):
+ """
+
+ tokens: ProjectConfigAuthTokens | Unset = UNSET
+ sessions: ProjectConfigAuthSessions | Unset = UNSET
+ signup: ProjectConfigAuthSignup | Unset = UNSET
+ rate_limits: ProjectConfigAuthRateLimits | Unset = UNSET
+ password: ProjectConfigAuthPassword | Unset = UNSET
+ password_reset: ProjectConfigAuthPasswordReset | Unset = UNSET
+ email_verification: ProjectConfigAuthEmailVerification | Unset = UNSET
+ cors: ProjectConfigAuthCORS | Unset = UNSET
+ providers: ProjectConfigAuthProviders | Unset = UNSET
+ email: ProjectConfigAuthEmail | Unset = UNSET
+ managed_pages: ProjectConfigAuthManagedPages | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_auth_cors import ProjectConfigAuthCORS
+ from ..models.project_config_auth_email import ProjectConfigAuthEmail
+ from ..models.project_config_auth_email_verification import ProjectConfigAuthEmailVerification
+ from ..models.project_config_auth_managed_pages import ProjectConfigAuthManagedPages
+ from ..models.project_config_auth_password import ProjectConfigAuthPassword
+ from ..models.project_config_auth_password_reset import ProjectConfigAuthPasswordReset
+ from ..models.project_config_auth_providers import ProjectConfigAuthProviders
+ from ..models.project_config_auth_rate_limits import ProjectConfigAuthRateLimits
+ from ..models.project_config_auth_sessions import ProjectConfigAuthSessions
+ from ..models.project_config_auth_signup import ProjectConfigAuthSignup
+ from ..models.project_config_auth_tokens import ProjectConfigAuthTokens
+ tokens: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.tokens, Unset):
+ tokens = self.tokens.to_dict()
+
+ sessions: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.sessions, Unset):
+ sessions = self.sessions.to_dict()
+
+ signup: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.signup, Unset):
+ signup = self.signup.to_dict()
+
+ rate_limits: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.rate_limits, Unset):
+ rate_limits = self.rate_limits.to_dict()
+
+ password: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.password, Unset):
+ password = self.password.to_dict()
+
+ password_reset: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.password_reset, Unset):
+ password_reset = self.password_reset.to_dict()
+
+ email_verification: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.email_verification, Unset):
+ email_verification = self.email_verification.to_dict()
+
+ cors: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.cors, Unset):
+ cors = self.cors.to_dict()
+
+ providers: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.providers, Unset):
+ providers = self.providers.to_dict()
+
+ email: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.email, Unset):
+ email = self.email.to_dict()
+
+ managed_pages: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.managed_pages, Unset):
+ managed_pages = self.managed_pages.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if tokens is not UNSET:
+ field_dict["tokens"] = tokens
+ if sessions is not UNSET:
+ field_dict["sessions"] = sessions
+ if signup is not UNSET:
+ field_dict["signup"] = signup
+ if rate_limits is not UNSET:
+ field_dict["rate_limits"] = rate_limits
+ if password is not UNSET:
+ field_dict["password"] = password
+ if password_reset is not UNSET:
+ field_dict["password_reset"] = password_reset
+ if email_verification is not UNSET:
+ field_dict["email_verification"] = email_verification
+ if cors is not UNSET:
+ field_dict["cors"] = cors
+ if providers is not UNSET:
+ field_dict["providers"] = providers
+ if email is not UNSET:
+ field_dict["email"] = email
+ if managed_pages is not UNSET:
+ field_dict["managed_pages"] = managed_pages
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_auth_cors import ProjectConfigAuthCORS
+ from ..models.project_config_auth_email import ProjectConfigAuthEmail
+ from ..models.project_config_auth_email_verification import ProjectConfigAuthEmailVerification
+ from ..models.project_config_auth_managed_pages import ProjectConfigAuthManagedPages
+ from ..models.project_config_auth_password import ProjectConfigAuthPassword
+ from ..models.project_config_auth_password_reset import ProjectConfigAuthPasswordReset
+ from ..models.project_config_auth_providers import ProjectConfigAuthProviders
+ from ..models.project_config_auth_rate_limits import ProjectConfigAuthRateLimits
+ from ..models.project_config_auth_sessions import ProjectConfigAuthSessions
+ from ..models.project_config_auth_signup import ProjectConfigAuthSignup
+ from ..models.project_config_auth_tokens import ProjectConfigAuthTokens
+ d = dict(src_dict)
+ _tokens = d.pop("tokens", UNSET)
+ tokens: ProjectConfigAuthTokens | Unset
+ if isinstance(_tokens, Unset):
+ tokens = UNSET
+ else:
+ tokens = ProjectConfigAuthTokens.from_dict(_tokens)
+
+
+
+
+ _sessions = d.pop("sessions", UNSET)
+ sessions: ProjectConfigAuthSessions | Unset
+ if isinstance(_sessions, Unset):
+ sessions = UNSET
+ else:
+ sessions = ProjectConfigAuthSessions.from_dict(_sessions)
+
+
+
+
+ _signup = d.pop("signup", UNSET)
+ signup: ProjectConfigAuthSignup | Unset
+ if isinstance(_signup, Unset):
+ signup = UNSET
+ else:
+ signup = ProjectConfigAuthSignup.from_dict(_signup)
+
+
+
+
+ _rate_limits = d.pop("rate_limits", UNSET)
+ rate_limits: ProjectConfigAuthRateLimits | Unset
+ if isinstance(_rate_limits, Unset):
+ rate_limits = UNSET
+ else:
+ rate_limits = ProjectConfigAuthRateLimits.from_dict(_rate_limits)
+
+
+
+
+ _password = d.pop("password", UNSET)
+ password: ProjectConfigAuthPassword | Unset
+ if isinstance(_password, Unset):
+ password = UNSET
+ else:
+ password = ProjectConfigAuthPassword.from_dict(_password)
+
+
+
+
+ _password_reset = d.pop("password_reset", UNSET)
+ password_reset: ProjectConfigAuthPasswordReset | Unset
+ if isinstance(_password_reset, Unset):
+ password_reset = UNSET
+ else:
+ password_reset = ProjectConfigAuthPasswordReset.from_dict(_password_reset)
+
+
+
+
+ _email_verification = d.pop("email_verification", UNSET)
+ email_verification: ProjectConfigAuthEmailVerification | Unset
+ if isinstance(_email_verification, Unset):
+ email_verification = UNSET
+ else:
+ email_verification = ProjectConfigAuthEmailVerification.from_dict(_email_verification)
+
+
+
+
+ _cors = d.pop("cors", UNSET)
+ cors: ProjectConfigAuthCORS | Unset
+ if isinstance(_cors, Unset):
+ cors = UNSET
+ else:
+ cors = ProjectConfigAuthCORS.from_dict(_cors)
+
+
+
+
+ _providers = d.pop("providers", UNSET)
+ providers: ProjectConfigAuthProviders | Unset
+ if isinstance(_providers, Unset):
+ providers = UNSET
+ else:
+ providers = ProjectConfigAuthProviders.from_dict(_providers)
+
+
+
+
+ _email = d.pop("email", UNSET)
+ email: ProjectConfigAuthEmail | Unset
+ if isinstance(_email, Unset):
+ email = UNSET
+ else:
+ email = ProjectConfigAuthEmail.from_dict(_email)
+
+
+
+
+ _managed_pages = d.pop("managed_pages", UNSET)
+ managed_pages: ProjectConfigAuthManagedPages | Unset
+ if isinstance(_managed_pages, Unset):
+ managed_pages = UNSET
+ else:
+ managed_pages = ProjectConfigAuthManagedPages.from_dict(_managed_pages)
+
+
+
+
+ project_config_auth = cls(
+ tokens=tokens,
+ sessions=sessions,
+ signup=signup,
+ rate_limits=rate_limits,
+ password=password,
+ password_reset=password_reset,
+ email_verification=email_verification,
+ cors=cors,
+ providers=providers,
+ email=email,
+ managed_pages=managed_pages,
+ )
+
+ return project_config_auth
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_cors.py b/src/volcano_sdk/_generated/models/project_config_auth_cors.py
new file mode 100644
index 00000000..7b0ca723
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_cors.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthCORS")
+
+
+
+@_attrs_define
+class ProjectConfigAuthCORS:
+ """
+ Attributes:
+ enabled (bool | Unset):
+ allowed_origins (list[str] | Unset):
+ allow_credentials (bool | Unset):
+ max_age (int | Unset):
+ """
+
+ enabled: bool | Unset = UNSET
+ allowed_origins: list[str] | Unset = UNSET
+ allow_credentials: bool | Unset = UNSET
+ max_age: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enabled = self.enabled
+
+ allowed_origins: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_origins, Unset):
+ allowed_origins = self.allowed_origins
+
+
+
+ allow_credentials = self.allow_credentials
+
+ max_age = self.max_age
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if allowed_origins is not UNSET:
+ field_dict["allowed_origins"] = allowed_origins
+ if allow_credentials is not UNSET:
+ field_dict["allow_credentials"] = allow_credentials
+ if max_age is not UNSET:
+ field_dict["max_age"] = max_age
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ allowed_origins = cast(list[str], d.pop("allowed_origins", UNSET))
+
+
+ allow_credentials = d.pop("allow_credentials", UNSET)
+
+ max_age = d.pop("max_age", UNSET)
+
+ project_config_auth_cors = cls(
+ enabled=enabled,
+ allowed_origins=allowed_origins,
+ allow_credentials=allow_credentials,
+ max_age=max_age,
+ )
+
+ return project_config_auth_cors
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_email.py b/src/volcano_sdk/_generated/models/project_config_auth_email.py
new file mode 100644
index 00000000..c31822ac
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_email.py
@@ -0,0 +1,132 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_auth_email_from import ProjectConfigAuthEmailFrom
+ from ..models.project_config_auth_email_smtp import ProjectConfigAuthEmailSMTP
+ from ..models.project_config_email_templates import ProjectConfigEmailTemplates
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthEmail")
+
+
+
+@_attrs_define
+class ProjectConfigAuthEmail:
+ """
+ Attributes:
+ enabled (bool | Unset): Enable transactional email sending
+ from_ (ProjectConfigAuthEmailFrom | Unset):
+ smtp (ProjectConfigAuthEmailSMTP | Unset):
+ templates (ProjectConfigEmailTemplates | Unset): Email templates keyed by type. Fully synced when declared -
+ template
+ types absent from a declared map revert to server defaults (custom
+ bodies deleted, subject overrides cleared). Custom template bodies
+ require the PRO plan; subject-only changes are available on FREE.
+ """
+
+ enabled: bool | Unset = UNSET
+ from_: ProjectConfigAuthEmailFrom | Unset = UNSET
+ smtp: ProjectConfigAuthEmailSMTP | Unset = UNSET
+ templates: ProjectConfigEmailTemplates | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_auth_email_from import ProjectConfigAuthEmailFrom
+ from ..models.project_config_auth_email_smtp import ProjectConfigAuthEmailSMTP
+ from ..models.project_config_email_templates import ProjectConfigEmailTemplates
+ enabled = self.enabled
+
+ from_: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.from_, Unset):
+ from_ = self.from_.to_dict()
+
+ smtp: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.smtp, Unset):
+ smtp = self.smtp.to_dict()
+
+ templates: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.templates, Unset):
+ templates = self.templates.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if from_ is not UNSET:
+ field_dict["from"] = from_
+ if smtp is not UNSET:
+ field_dict["smtp"] = smtp
+ if templates is not UNSET:
+ field_dict["templates"] = templates
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_auth_email_from import ProjectConfigAuthEmailFrom
+ from ..models.project_config_auth_email_smtp import ProjectConfigAuthEmailSMTP
+ from ..models.project_config_email_templates import ProjectConfigEmailTemplates
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ _from_ = d.pop("from", UNSET)
+ from_: ProjectConfigAuthEmailFrom | Unset
+ if isinstance(_from_, Unset):
+ from_ = UNSET
+ else:
+ from_ = ProjectConfigAuthEmailFrom.from_dict(_from_)
+
+
+
+
+ _smtp = d.pop("smtp", UNSET)
+ smtp: ProjectConfigAuthEmailSMTP | Unset
+ if isinstance(_smtp, Unset):
+ smtp = UNSET
+ else:
+ smtp = ProjectConfigAuthEmailSMTP.from_dict(_smtp)
+
+
+
+
+ _templates = d.pop("templates", UNSET)
+ templates: ProjectConfigEmailTemplates | Unset
+ if isinstance(_templates, Unset):
+ templates = UNSET
+ else:
+ templates = ProjectConfigEmailTemplates.from_dict(_templates)
+
+
+
+
+ project_config_auth_email = cls(
+ enabled=enabled,
+ from_=from_,
+ smtp=smtp,
+ templates=templates,
+ )
+
+ return project_config_auth_email
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_email_from.py b/src/volcano_sdk/_generated/models/project_config_auth_email_from.py
new file mode 100644
index 00000000..a841d893
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_email_from.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthEmailFrom")
+
+
+
+@_attrs_define
+class ProjectConfigAuthEmailFrom:
+ """
+ Attributes:
+ address (str | Unset):
+ name (str | Unset):
+ """
+
+ address: str | Unset = UNSET
+ name: str | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ address = self.address
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if address is not UNSET:
+ field_dict["address"] = address
+ if name is not UNSET:
+ field_dict["name"] = name
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ address = d.pop("address", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ project_config_auth_email_from = cls(
+ address=address,
+ name=name,
+ )
+
+ return project_config_auth_email_from
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_email_password_provider.py b/src/volcano_sdk/_generated/models/project_config_auth_email_password_provider.py
new file mode 100644
index 00000000..315606fd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_email_password_provider.py
@@ -0,0 +1,60 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthEmailPasswordProvider")
+
+
+
+@_attrs_define
+class ProjectConfigAuthEmailPasswordProvider:
+ """
+ Attributes:
+ enabled (bool | Unset):
+ """
+
+ enabled: bool | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enabled = self.enabled
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ project_config_auth_email_password_provider = cls(
+ enabled=enabled,
+ )
+
+ return project_config_auth_email_password_provider
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_email_smtp.py b/src/volcano_sdk/_generated/models/project_config_auth_email_smtp.py
new file mode 100644
index 00000000..031c7643
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_email_smtp.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthEmailSMTP")
+
+
+
+@_attrs_define
+class ProjectConfigAuthEmailSMTP:
+ """
+ Attributes:
+ host (str | Unset):
+ port (int | Unset):
+ username (str | Unset):
+ password (str | Unset): Write-only; omitted from config export.
+ use_tls (bool | Unset):
+ """
+
+ host: str | Unset = UNSET
+ port: int | Unset = UNSET
+ username: str | Unset = UNSET
+ password: str | Unset = UNSET
+ use_tls: bool | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ host = self.host
+
+ port = self.port
+
+ username = self.username
+
+ password = self.password
+
+ use_tls = self.use_tls
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if host is not UNSET:
+ field_dict["host"] = host
+ if port is not UNSET:
+ field_dict["port"] = port
+ if username is not UNSET:
+ field_dict["username"] = username
+ if password is not UNSET:
+ field_dict["password"] = password
+ if use_tls is not UNSET:
+ field_dict["use_tls"] = use_tls
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ host = d.pop("host", UNSET)
+
+ port = d.pop("port", UNSET)
+
+ username = d.pop("username", UNSET)
+
+ password = d.pop("password", UNSET)
+
+ use_tls = d.pop("use_tls", UNSET)
+
+ project_config_auth_email_smtp = cls(
+ host=host,
+ port=port,
+ username=username,
+ password=password,
+ use_tls=use_tls,
+ )
+
+ return project_config_auth_email_smtp
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_email_verification.py b/src/volcano_sdk/_generated/models/project_config_auth_email_verification.py
new file mode 100644
index 00000000..c9652c76
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_email_verification.py
@@ -0,0 +1,70 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthEmailVerification")
+
+
+
+@_attrs_define
+class ProjectConfigAuthEmailVerification:
+ """
+ Attributes:
+ require_confirmation (bool | Unset): Require users to confirm email before sign-in. Requires email sending to be
+ enabled.
+ confirmation_timeout (int | Unset): Email confirmation token expiry in seconds
+ """
+
+ require_confirmation: bool | Unset = UNSET
+ confirmation_timeout: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ require_confirmation = self.require_confirmation
+
+ confirmation_timeout = self.confirmation_timeout
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if require_confirmation is not UNSET:
+ field_dict["require_confirmation"] = require_confirmation
+ if confirmation_timeout is not UNSET:
+ field_dict["confirmation_timeout"] = confirmation_timeout
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ require_confirmation = d.pop("require_confirmation", UNSET)
+
+ confirmation_timeout = d.pop("confirmation_timeout", UNSET)
+
+ project_config_auth_email_verification = cls(
+ require_confirmation=require_confirmation,
+ confirmation_timeout=confirmation_timeout,
+ )
+
+ return project_config_auth_email_verification
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_managed_pages.py b/src/volcano_sdk/_generated/models/project_config_auth_managed_pages.py
new file mode 100644
index 00000000..71130c87
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_managed_pages.py
@@ -0,0 +1,107 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_auth_redirects import ProjectConfigAuthRedirects
+ from ..models.project_config_hosted_pages import ProjectConfigHostedPages
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthManagedPages")
+
+
+
+@_attrs_define
+class ProjectConfigAuthManagedPages:
+ """
+ Attributes:
+ enabled (bool | Unset): Enable or disable managed auth hosted pages
+ redirects (ProjectConfigAuthRedirects | Unset):
+ pages (ProjectConfigHostedPages | Unset): Hosted auth pages keyed by page type (PRO plan). Upsert-only: omitted
+ pages are left untouched (there is no delete for hosted pages).
+ """
+
+ enabled: bool | Unset = UNSET
+ redirects: ProjectConfigAuthRedirects | Unset = UNSET
+ pages: ProjectConfigHostedPages | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_auth_redirects import ProjectConfigAuthRedirects
+ from ..models.project_config_hosted_pages import ProjectConfigHostedPages
+ enabled = self.enabled
+
+ redirects: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.redirects, Unset):
+ redirects = self.redirects.to_dict()
+
+ pages: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.pages, Unset):
+ pages = self.pages.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if redirects is not UNSET:
+ field_dict["redirects"] = redirects
+ if pages is not UNSET:
+ field_dict["pages"] = pages
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_auth_redirects import ProjectConfigAuthRedirects
+ from ..models.project_config_hosted_pages import ProjectConfigHostedPages
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ _redirects = d.pop("redirects", UNSET)
+ redirects: ProjectConfigAuthRedirects | Unset
+ if isinstance(_redirects, Unset):
+ redirects = UNSET
+ else:
+ redirects = ProjectConfigAuthRedirects.from_dict(_redirects)
+
+
+
+
+ _pages = d.pop("pages", UNSET)
+ pages: ProjectConfigHostedPages | Unset
+ if isinstance(_pages, Unset):
+ pages = UNSET
+ else:
+ pages = ProjectConfigHostedPages.from_dict(_pages)
+
+
+
+
+ project_config_auth_managed_pages = cls(
+ enabled=enabled,
+ redirects=redirects,
+ pages=pages,
+ )
+
+ return project_config_auth_managed_pages
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_password.py b/src/volcano_sdk/_generated/models/project_config_auth_password.py
new file mode 100644
index 00000000..86e772ef
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_password.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthPassword")
+
+
+
+@_attrs_define
+class ProjectConfigAuthPassword:
+ """
+ Attributes:
+ min_length (int | Unset):
+ require_uppercase (bool | Unset):
+ require_lowercase (bool | Unset):
+ require_numbers (bool | Unset):
+ require_special_chars (bool | Unset):
+ """
+
+ min_length: int | Unset = UNSET
+ require_uppercase: bool | Unset = UNSET
+ require_lowercase: bool | Unset = UNSET
+ require_numbers: bool | Unset = UNSET
+ require_special_chars: bool | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ min_length = self.min_length
+
+ require_uppercase = self.require_uppercase
+
+ require_lowercase = self.require_lowercase
+
+ require_numbers = self.require_numbers
+
+ require_special_chars = self.require_special_chars
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if min_length is not UNSET:
+ field_dict["min_length"] = min_length
+ if require_uppercase is not UNSET:
+ field_dict["require_uppercase"] = require_uppercase
+ if require_lowercase is not UNSET:
+ field_dict["require_lowercase"] = require_lowercase
+ if require_numbers is not UNSET:
+ field_dict["require_numbers"] = require_numbers
+ if require_special_chars is not UNSET:
+ field_dict["require_special_chars"] = require_special_chars
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ min_length = d.pop("min_length", UNSET)
+
+ require_uppercase = d.pop("require_uppercase", UNSET)
+
+ require_lowercase = d.pop("require_lowercase", UNSET)
+
+ require_numbers = d.pop("require_numbers", UNSET)
+
+ require_special_chars = d.pop("require_special_chars", UNSET)
+
+ project_config_auth_password = cls(
+ min_length=min_length,
+ require_uppercase=require_uppercase,
+ require_lowercase=require_lowercase,
+ require_numbers=require_numbers,
+ require_special_chars=require_special_chars,
+ )
+
+ return project_config_auth_password
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_password_reset.py b/src/volcano_sdk/_generated/models/project_config_auth_password_reset.py
new file mode 100644
index 00000000..449dcc24
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_password_reset.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthPasswordReset")
+
+
+
+@_attrs_define
+class ProjectConfigAuthPasswordReset:
+ """
+ Attributes:
+ allow (bool | Unset):
+ timeout (int | Unset): Password reset token expiry in seconds
+ max_history (int | Unset): Number of previous passwords to disallow (0=disabled)
+ """
+
+ allow: bool | Unset = UNSET
+ timeout: int | Unset = UNSET
+ max_history: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ allow = self.allow
+
+ timeout = self.timeout
+
+ max_history = self.max_history
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if allow is not UNSET:
+ field_dict["allow"] = allow
+ if timeout is not UNSET:
+ field_dict["timeout"] = timeout
+ if max_history is not UNSET:
+ field_dict["max_history"] = max_history
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ allow = d.pop("allow", UNSET)
+
+ timeout = d.pop("timeout", UNSET)
+
+ max_history = d.pop("max_history", UNSET)
+
+ project_config_auth_password_reset = cls(
+ allow=allow,
+ timeout=timeout,
+ max_history=max_history,
+ )
+
+ return project_config_auth_password_reset
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_providers.py b/src/volcano_sdk/_generated/models/project_config_auth_providers.py
new file mode 100644
index 00000000..6ddea8d1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_providers.py
@@ -0,0 +1,105 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_auth_email_password_provider import ProjectConfigAuthEmailPasswordProvider
+ from ..models.project_config_o_auth_provider import ProjectConfigOAuthProvider
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthProviders")
+
+
+
+@_attrs_define
+class ProjectConfigAuthProviders:
+ """
+ Attributes:
+ email_password (ProjectConfigAuthEmailPasswordProvider | Unset):
+ oauth (list[ProjectConfigOAuthProvider] | Unset): Fully synced when declared - providers absent from this list
+ are deleted.
+ """
+
+ email_password: ProjectConfigAuthEmailPasswordProvider | Unset = UNSET
+ oauth: list[ProjectConfigOAuthProvider] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_auth_email_password_provider import ProjectConfigAuthEmailPasswordProvider
+ from ..models.project_config_o_auth_provider import ProjectConfigOAuthProvider
+ email_password: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.email_password, Unset):
+ email_password = self.email_password.to_dict()
+
+ oauth: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.oauth, Unset):
+ oauth = []
+ for oauth_item_data in self.oauth:
+ oauth_item = oauth_item_data.to_dict()
+ oauth.append(oauth_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if email_password is not UNSET:
+ field_dict["email_password"] = email_password
+ if oauth is not UNSET:
+ field_dict["oauth"] = oauth
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_auth_email_password_provider import ProjectConfigAuthEmailPasswordProvider
+ from ..models.project_config_o_auth_provider import ProjectConfigOAuthProvider
+ d = dict(src_dict)
+ _email_password = d.pop("email_password", UNSET)
+ email_password: ProjectConfigAuthEmailPasswordProvider | Unset
+ if isinstance(_email_password, Unset):
+ email_password = UNSET
+ else:
+ email_password = ProjectConfigAuthEmailPasswordProvider.from_dict(_email_password)
+
+
+
+
+ _oauth = d.pop("oauth", UNSET)
+ oauth: list[ProjectConfigOAuthProvider] | Unset = UNSET
+ if _oauth is not UNSET:
+ oauth = []
+ for oauth_item_data in _oauth:
+ oauth_item = ProjectConfigOAuthProvider.from_dict(oauth_item_data)
+
+
+
+ oauth.append(oauth_item)
+
+
+ project_config_auth_providers = cls(
+ email_password=email_password,
+ oauth=oauth,
+ )
+
+ return project_config_auth_providers
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_rate_limits.py b/src/volcano_sdk/_generated/models/project_config_auth_rate_limits.py
new file mode 100644
index 00000000..93bc9753
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_rate_limits.py
@@ -0,0 +1,88 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthRateLimits")
+
+
+
+@_attrs_define
+class ProjectConfigAuthRateLimits:
+ """ Rate limits per hour.
+
+ Attributes:
+ signup (int | Unset):
+ signin (int | Unset):
+ token_refresh (int | Unset):
+ password_reset (int | Unset):
+ """
+
+ signup: int | Unset = UNSET
+ signin: int | Unset = UNSET
+ token_refresh: int | Unset = UNSET
+ password_reset: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ signup = self.signup
+
+ signin = self.signin
+
+ token_refresh = self.token_refresh
+
+ password_reset = self.password_reset
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if signup is not UNSET:
+ field_dict["signup"] = signup
+ if signin is not UNSET:
+ field_dict["signin"] = signin
+ if token_refresh is not UNSET:
+ field_dict["token_refresh"] = token_refresh
+ if password_reset is not UNSET:
+ field_dict["password_reset"] = password_reset
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ signup = d.pop("signup", UNSET)
+
+ signin = d.pop("signin", UNSET)
+
+ token_refresh = d.pop("token_refresh", UNSET)
+
+ password_reset = d.pop("password_reset", UNSET)
+
+ project_config_auth_rate_limits = cls(
+ signup=signup,
+ signin=signin,
+ token_refresh=token_refresh,
+ password_reset=password_reset,
+ )
+
+ return project_config_auth_rate_limits
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_redirects.py b/src/volcano_sdk/_generated/models/project_config_auth_redirects.py
new file mode 100644
index 00000000..33a2382c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_redirects.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthRedirects")
+
+
+
+@_attrs_define
+class ProjectConfigAuthRedirects:
+ """
+ Attributes:
+ allowed (list[str] | Unset): Redirect allowlist. Every entry must be a valid http/https URL.
+ post_auth (str | Unset): Must be included in `allowed` when set.
+ post_logout (str | Unset): Must be included in `allowed` when set.
+ device_verification (str | Unset): Optional custom device-authorization verification page URL.
+ """
+
+ allowed: list[str] | Unset = UNSET
+ post_auth: str | Unset = UNSET
+ post_logout: str | Unset = UNSET
+ device_verification: str | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ allowed: list[str] | Unset = UNSET
+ if not isinstance(self.allowed, Unset):
+ allowed = self.allowed
+
+
+
+ post_auth = self.post_auth
+
+ post_logout = self.post_logout
+
+ device_verification = self.device_verification
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if allowed is not UNSET:
+ field_dict["allowed"] = allowed
+ if post_auth is not UNSET:
+ field_dict["post_auth"] = post_auth
+ if post_logout is not UNSET:
+ field_dict["post_logout"] = post_logout
+ if device_verification is not UNSET:
+ field_dict["device_verification"] = device_verification
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ allowed = cast(list[str], d.pop("allowed", UNSET))
+
+
+ post_auth = d.pop("post_auth", UNSET)
+
+ post_logout = d.pop("post_logout", UNSET)
+
+ device_verification = d.pop("device_verification", UNSET)
+
+ project_config_auth_redirects = cls(
+ allowed=allowed,
+ post_auth=post_auth,
+ post_logout=post_logout,
+ device_verification=device_verification,
+ )
+
+ return project_config_auth_redirects
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_sessions.py b/src/volcano_sdk/_generated/models/project_config_auth_sessions.py
new file mode 100644
index 00000000..2a2680ce
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_sessions.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthSessions")
+
+
+
+@_attrs_define
+class ProjectConfigAuthSessions:
+ """
+ Attributes:
+ inactivity_timeout (int | Unset): Force re-login after inactivity (seconds, 0=never)
+ max_session_duration (int | Unset): Force re-login after duration (seconds, 0=never)
+ """
+
+ inactivity_timeout: int | Unset = UNSET
+ max_session_duration: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ inactivity_timeout = self.inactivity_timeout
+
+ max_session_duration = self.max_session_duration
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if inactivity_timeout is not UNSET:
+ field_dict["inactivity_timeout"] = inactivity_timeout
+ if max_session_duration is not UNSET:
+ field_dict["max_session_duration"] = max_session_duration
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ inactivity_timeout = d.pop("inactivity_timeout", UNSET)
+
+ max_session_duration = d.pop("max_session_duration", UNSET)
+
+ project_config_auth_sessions = cls(
+ inactivity_timeout=inactivity_timeout,
+ max_session_duration=max_session_duration,
+ )
+
+ return project_config_auth_sessions
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_signup.py b/src/volcano_sdk/_generated/models/project_config_auth_signup.py
new file mode 100644
index 00000000..3b78d39d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_signup.py
@@ -0,0 +1,118 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_auth_signup_allowed_email_domains_mode import check_project_config_auth_signup_allowed_email_domains_mode
+from ..models.project_config_auth_signup_allowed_email_domains_mode import ProjectConfigAuthSignupAllowedEmailDomainsMode
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthSignup")
+
+
+
+@_attrs_define
+class ProjectConfigAuthSignup:
+ """
+ Attributes:
+ enable_signup (bool | Unset): Master switch for signups across ALL providers
+ enable_anonymous_signins (bool | Unset):
+ allowed_email_domains (list[str] | Unset): Email domains allowed to create users. Empty allows every domain.
+ Replaces the stored list; entries are normalized (lowercase, no `@`
+ prefix) and must be bare domains such as `domain1.com`. Matching is
+ exact, so subdomains need their own entry. At most 100 entries.
+
+ Restricting signups is a PRO feature to configure and to enforce: a
+ FREE project can only declare the list it already has or remove the
+ restriction, and the list it keeps is parked until it upgrades.
+ Example: ['domain1.com', 'domain2.com'].
+ allowed_email_domains_mode (ProjectConfigAuthSignupAllowedEmailDomainsMode | Unset): How far
+ `allowed_email_domains` reaches. `signup` gates account
+ creation only. `signup_and_signin` also blocks sign-in for accounts
+ outside the list and signs out the ones it locks out. `disabled`
+ keeps the list without enforcing it.
+ """
+
+ enable_signup: bool | Unset = UNSET
+ enable_anonymous_signins: bool | Unset = UNSET
+ allowed_email_domains: list[str] | Unset = UNSET
+ allowed_email_domains_mode: ProjectConfigAuthSignupAllowedEmailDomainsMode | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enable_signup = self.enable_signup
+
+ enable_anonymous_signins = self.enable_anonymous_signins
+
+ allowed_email_domains: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_email_domains, Unset):
+ allowed_email_domains = self.allowed_email_domains
+
+
+
+ allowed_email_domains_mode: str | Unset = UNSET
+ if not isinstance(self.allowed_email_domains_mode, Unset):
+ allowed_email_domains_mode = self.allowed_email_domains_mode
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if enable_signup is not UNSET:
+ field_dict["enable_signup"] = enable_signup
+ if enable_anonymous_signins is not UNSET:
+ field_dict["enable_anonymous_signins"] = enable_anonymous_signins
+ if allowed_email_domains is not UNSET:
+ field_dict["allowed_email_domains"] = allowed_email_domains
+ if allowed_email_domains_mode is not UNSET:
+ field_dict["allowed_email_domains_mode"] = allowed_email_domains_mode
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enable_signup = d.pop("enable_signup", UNSET)
+
+ enable_anonymous_signins = d.pop("enable_anonymous_signins", UNSET)
+
+ allowed_email_domains = cast(list[str], d.pop("allowed_email_domains", UNSET))
+
+
+ _allowed_email_domains_mode = d.pop("allowed_email_domains_mode", UNSET)
+ allowed_email_domains_mode: ProjectConfigAuthSignupAllowedEmailDomainsMode | Unset
+ if isinstance(_allowed_email_domains_mode, Unset):
+ allowed_email_domains_mode = UNSET
+ else:
+ allowed_email_domains_mode = check_project_config_auth_signup_allowed_email_domains_mode(_allowed_email_domains_mode)
+
+
+
+
+ project_config_auth_signup = cls(
+ enable_signup=enable_signup,
+ enable_anonymous_signins=enable_anonymous_signins,
+ allowed_email_domains=allowed_email_domains,
+ allowed_email_domains_mode=allowed_email_domains_mode,
+ )
+
+ return project_config_auth_signup
+
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_signup_allowed_email_domains_mode.py b/src/volcano_sdk/_generated/models/project_config_auth_signup_allowed_email_domains_mode.py
new file mode 100644
index 00000000..a50c6681
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_signup_allowed_email_domains_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigAuthSignupAllowedEmailDomainsMode = Literal['disabled', 'signup', 'signup_and_signin']
+
+PROJECT_CONFIG_AUTH_SIGNUP_ALLOWED_EMAIL_DOMAINS_MODE_VALUES: set[ProjectConfigAuthSignupAllowedEmailDomainsMode] = { 'disabled', 'signup', 'signup_and_signin', }
+
+def check_project_config_auth_signup_allowed_email_domains_mode(value: str) -> ProjectConfigAuthSignupAllowedEmailDomainsMode:
+ if value in PROJECT_CONFIG_AUTH_SIGNUP_ALLOWED_EMAIL_DOMAINS_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_AUTH_SIGNUP_ALLOWED_EMAIL_DOMAINS_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_auth_tokens.py b/src/volcano_sdk/_generated/models/project_config_auth_tokens.py
new file mode 100644
index 00000000..36c099a1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_auth_tokens.py
@@ -0,0 +1,88 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigAuthTokens")
+
+
+
+@_attrs_define
+class ProjectConfigAuthTokens:
+ """ Token lifetimes in seconds.
+
+ Attributes:
+ access_token_lifetime (int | Unset):
+ refresh_token_lifetime (int | Unset):
+ refresh_token_reuse_interval (int | Unset):
+ platform_token_ttl (int | Unset):
+ """
+
+ access_token_lifetime: int | Unset = UNSET
+ refresh_token_lifetime: int | Unset = UNSET
+ refresh_token_reuse_interval: int | Unset = UNSET
+ platform_token_ttl: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ access_token_lifetime = self.access_token_lifetime
+
+ refresh_token_lifetime = self.refresh_token_lifetime
+
+ refresh_token_reuse_interval = self.refresh_token_reuse_interval
+
+ platform_token_ttl = self.platform_token_ttl
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if access_token_lifetime is not UNSET:
+ field_dict["access_token_lifetime"] = access_token_lifetime
+ if refresh_token_lifetime is not UNSET:
+ field_dict["refresh_token_lifetime"] = refresh_token_lifetime
+ if refresh_token_reuse_interval is not UNSET:
+ field_dict["refresh_token_reuse_interval"] = refresh_token_reuse_interval
+ if platform_token_ttl is not UNSET:
+ field_dict["platform_token_ttl"] = platform_token_ttl
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ access_token_lifetime = d.pop("access_token_lifetime", UNSET)
+
+ refresh_token_lifetime = d.pop("refresh_token_lifetime", UNSET)
+
+ refresh_token_reuse_interval = d.pop("refresh_token_reuse_interval", UNSET)
+
+ platform_token_ttl = d.pop("platform_token_ttl", UNSET)
+
+ project_config_auth_tokens = cls(
+ access_token_lifetime=access_token_lifetime,
+ refresh_token_lifetime=refresh_token_lifetime,
+ refresh_token_reuse_interval=refresh_token_reuse_interval,
+ platform_token_ttl=platform_token_ttl,
+ )
+
+ return project_config_auth_tokens
+
diff --git a/src/volcano_sdk/_generated/models/project_config_bucket.py b/src/volcano_sdk/_generated/models/project_config_bucket.py
new file mode 100644
index 00000000..b5a4335b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_bucket.py
@@ -0,0 +1,118 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_bucket_policy import ProjectConfigBucketPolicy
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigBucket")
+
+
+
+@_attrs_define
+class ProjectConfigBucket:
+ """ Settings for an existing storage bucket. Buckets are never created or
+ deleted through the manifest. When `policies` is declared it is fully
+ synced (policies absent from the list are deleted; an empty list
+ deletes all); omitting `policies` leaves the bucket's policies
+ untouched.
+
+ Attributes:
+ name (str):
+ file_size_limit (int | Unset): Maximum file size in bytes
+ allowed_mime_types (list[str] | Unset):
+ policies (list[ProjectConfigBucketPolicy] | Unset):
+ """
+
+ name: str
+ file_size_limit: int | Unset = UNSET
+ allowed_mime_types: list[str] | Unset = UNSET
+ policies: list[ProjectConfigBucketPolicy] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_bucket_policy import ProjectConfigBucketPolicy
+ name = self.name
+
+ file_size_limit = self.file_size_limit
+
+ allowed_mime_types: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_mime_types, Unset):
+ allowed_mime_types = self.allowed_mime_types
+
+
+
+ policies: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.policies, Unset):
+ policies = []
+ for policies_item_data in self.policies:
+ policies_item = policies_item_data.to_dict()
+ policies.append(policies_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "name": name,
+ })
+ if file_size_limit is not UNSET:
+ field_dict["file_size_limit"] = file_size_limit
+ if allowed_mime_types is not UNSET:
+ field_dict["allowed_mime_types"] = allowed_mime_types
+ if policies is not UNSET:
+ field_dict["policies"] = policies
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_bucket_policy import ProjectConfigBucketPolicy
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ file_size_limit = d.pop("file_size_limit", UNSET)
+
+ allowed_mime_types = cast(list[str], d.pop("allowed_mime_types", UNSET))
+
+
+ _policies = d.pop("policies", UNSET)
+ policies: list[ProjectConfigBucketPolicy] | Unset = UNSET
+ if _policies is not UNSET:
+ policies = []
+ for policies_item_data in _policies:
+ policies_item = ProjectConfigBucketPolicy.from_dict(policies_item_data)
+
+
+
+ policies.append(policies_item)
+
+
+ project_config_bucket = cls(
+ name=name,
+ file_size_limit=file_size_limit,
+ allowed_mime_types=allowed_mime_types,
+ policies=policies,
+ )
+
+ return project_config_bucket
+
diff --git a/src/volcano_sdk/_generated/models/project_config_bucket_policy.py b/src/volcano_sdk/_generated/models/project_config_bucket_policy.py
new file mode 100644
index 00000000..19eb8fab
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_bucket_policy.py
@@ -0,0 +1,80 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_bucket_policy_operation import check_project_config_bucket_policy_operation
+from ..models.project_config_bucket_policy_operation import ProjectConfigBucketPolicyOperation
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigBucketPolicy")
+
+
+
+@_attrs_define
+class ProjectConfigBucketPolicy:
+ """
+ Attributes:
+ name (str):
+ operation (ProjectConfigBucketPolicyOperation):
+ definition (str): Policy expression
+ """
+
+ name: str
+ operation: ProjectConfigBucketPolicyOperation
+ definition: str
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ operation: str = self.operation
+
+ definition = self.definition
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "name": name,
+ "operation": operation,
+ "definition": definition,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ operation = check_project_config_bucket_policy_operation(d.pop("operation"))
+
+
+
+
+ definition = d.pop("definition")
+
+ project_config_bucket_policy = cls(
+ name=name,
+ operation=operation,
+ definition=definition,
+ )
+
+ return project_config_bucket_policy
+
diff --git a/src/volcano_sdk/_generated/models/project_config_bucket_policy_operation.py b/src/volcano_sdk/_generated/models/project_config_bucket_policy_operation.py
new file mode 100644
index 00000000..53be936f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_bucket_policy_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigBucketPolicyOperation = Literal['DELETE', 'INSERT', 'SELECT', 'UPDATE']
+
+PROJECT_CONFIG_BUCKET_POLICY_OPERATION_VALUES: set[ProjectConfigBucketPolicyOperation] = { 'DELETE', 'INSERT', 'SELECT', 'UPDATE', }
+
+def check_project_config_bucket_policy_operation(value: str) -> ProjectConfigBucketPolicyOperation:
+ if value in PROJECT_CONFIG_BUCKET_POLICY_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_BUCKET_POLICY_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_custom_domain.py b/src/volcano_sdk/_generated/models/project_config_custom_domain.py
new file mode 100644
index 00000000..8220362f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_custom_domain.py
@@ -0,0 +1,88 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.frontend_custom_domain_tls_config import FrontendCustomDomainTLSConfig
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigCustomDomain")
+
+
+
+@_attrs_define
+class ProjectConfigCustomDomain:
+ """ Custom domain with BYOC TLS (PRO plan). `tls` is required when the
+ domain is first created and optional afterwards: providing new TLS
+ material for the same domain rotates the certificate in place (zero
+ downtime); omitting `tls` keeps the stored certificate. TLS material is
+ write-only and omitted from config export.
+
+ Attributes:
+ domain (str): Fully-qualified domain name (hostname only, no scheme/path)
+ tls (FrontendCustomDomainTLSConfig | Unset):
+ """
+
+ domain: str
+ tls: FrontendCustomDomainTLSConfig | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend_custom_domain_tls_config import FrontendCustomDomainTLSConfig
+ domain = self.domain
+
+ tls: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.tls, Unset):
+ tls = self.tls.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "domain": domain,
+ })
+ if tls is not UNSET:
+ field_dict["tls"] = tls
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend_custom_domain_tls_config import FrontendCustomDomainTLSConfig
+ d = dict(src_dict)
+ domain = d.pop("domain")
+
+ _tls = d.pop("tls", UNSET)
+ tls: FrontendCustomDomainTLSConfig | Unset
+ if isinstance(_tls, Unset):
+ tls = UNSET
+ else:
+ tls = FrontendCustomDomainTLSConfig.from_dict(_tls)
+
+
+
+
+ project_config_custom_domain = cls(
+ domain=domain,
+ tls=tls,
+ )
+
+ return project_config_custom_domain
+
diff --git a/src/volcano_sdk/_generated/models/project_config_database.py b/src/volcano_sdk/_generated/models/project_config_database.py
new file mode 100644
index 00000000..7fdcbb5e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_database.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_database_database_type import check_project_config_database_database_type
+from ..models.project_config_database_database_type import ProjectConfigDatabaseDatabaseType
+from ..models.project_config_database_pg_version import check_project_config_database_pg_version
+from ..models.project_config_database_pg_version import ProjectConfigDatabasePgVersion
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigDatabase")
+
+
+
+@_attrs_define
+class ProjectConfigDatabase:
+ """ Assertion-only entry for an existing database. No database property is
+ mutable through the manifest; declared values are compared against the
+ deployed database and any mismatch fails validation. Databases are
+ never created or deleted here.
+
+ Attributes:
+ name (str):
+ region (str): Deployed region ID (e.g. aws-us-east-1). Asserted, never written.
+ pg_version (ProjectConfigDatabasePgVersion): PostgreSQL major version. Asserted, never written.
+ database_type (ProjectConfigDatabaseDatabaseType | Unset): Compute tier. Asserted, never written - tier changes
+ are not
+ supported via the manifest; use the databases API/CLI/GUI instead.
+ """
+
+ name: str
+ region: str
+ pg_version: ProjectConfigDatabasePgVersion
+ database_type: ProjectConfigDatabaseDatabaseType | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ region = self.region
+
+ pg_version: str = self.pg_version
+
+ database_type: str | Unset = UNSET
+ if not isinstance(self.database_type, Unset):
+ database_type = self.database_type
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "name": name,
+ "region": region,
+ "pg_version": pg_version,
+ })
+ if database_type is not UNSET:
+ field_dict["database_type"] = database_type
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ region = d.pop("region")
+
+ pg_version = check_project_config_database_pg_version(d.pop("pg_version"))
+
+
+
+
+ _database_type = d.pop("database_type", UNSET)
+ database_type: ProjectConfigDatabaseDatabaseType | Unset
+ if isinstance(_database_type, Unset):
+ database_type = UNSET
+ else:
+ database_type = check_project_config_database_database_type(_database_type)
+
+
+
+
+ project_config_database = cls(
+ name=name,
+ region=region,
+ pg_version=pg_version,
+ database_type=database_type,
+ )
+
+ return project_config_database
+
diff --git a/src/volcano_sdk/_generated/models/project_config_database_database_type.py b/src/volcano_sdk/_generated/models/project_config_database_database_type.py
new file mode 100644
index 00000000..9e1d3628
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_database_database_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigDatabaseDatabaseType = Literal['volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs']
+
+PROJECT_CONFIG_DATABASE_DATABASE_TYPE_VALUES: set[ProjectConfigDatabaseDatabaseType] = { 'volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs', }
+
+def check_project_config_database_database_type(value: str) -> ProjectConfigDatabaseDatabaseType:
+ if value in PROJECT_CONFIG_DATABASE_DATABASE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_DATABASE_DATABASE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_database_pg_version.py b/src/volcano_sdk/_generated/models/project_config_database_pg_version.py
new file mode 100644
index 00000000..a3c3391c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_database_pg_version.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigDatabasePgVersion = Literal['15', '16']
+
+PROJECT_CONFIG_DATABASE_PG_VERSION_VALUES: set[ProjectConfigDatabasePgVersion] = { '15', '16', }
+
+def check_project_config_database_pg_version(value: str) -> ProjectConfigDatabasePgVersion:
+ if value in PROJECT_CONFIG_DATABASE_PG_VERSION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_DATABASE_PG_VERSION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_email_template.py b/src/volcano_sdk/_generated/models/project_config_email_template.py
new file mode 100644
index 00000000..bd6fa948
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_email_template.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigEmailTemplate")
+
+
+
+@_attrs_define
+class ProjectConfigEmailTemplate:
+ """
+ Attributes:
+ subject (str | Unset):
+ html_body (str | Unset): HTML body. Max 256 KiB. PRO plan required for custom bodies.
+ text_body (str | Unset): Plain-text body. Max 256 KiB. PRO plan required for custom bodies.
+ """
+
+ subject: str | Unset = UNSET
+ html_body: str | Unset = UNSET
+ text_body: str | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ subject = self.subject
+
+ html_body = self.html_body
+
+ text_body = self.text_body
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if subject is not UNSET:
+ field_dict["subject"] = subject
+ if html_body is not UNSET:
+ field_dict["html_body"] = html_body
+ if text_body is not UNSET:
+ field_dict["text_body"] = text_body
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ subject = d.pop("subject", UNSET)
+
+ html_body = d.pop("html_body", UNSET)
+
+ text_body = d.pop("text_body", UNSET)
+
+ project_config_email_template = cls(
+ subject=subject,
+ html_body=html_body,
+ text_body=text_body,
+ )
+
+ return project_config_email_template
+
diff --git a/src/volcano_sdk/_generated/models/project_config_email_templates.py b/src/volcano_sdk/_generated/models/project_config_email_templates.py
new file mode 100644
index 00000000..ed645f0c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_email_templates.py
@@ -0,0 +1,136 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_email_template import ProjectConfigEmailTemplate
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigEmailTemplates")
+
+
+
+@_attrs_define
+class ProjectConfigEmailTemplates:
+ """ Email templates keyed by type. Fully synced when declared - template
+ types absent from a declared map revert to server defaults (custom
+ bodies deleted, subject overrides cleared). Custom template bodies
+ require the PRO plan; subject-only changes are available on FREE.
+
+ Attributes:
+ confirmation (ProjectConfigEmailTemplate | Unset):
+ password_reset (ProjectConfigEmailTemplate | Unset):
+ password_changed (ProjectConfigEmailTemplate | Unset):
+ welcome (ProjectConfigEmailTemplate | Unset):
+ """
+
+ confirmation: ProjectConfigEmailTemplate | Unset = UNSET
+ password_reset: ProjectConfigEmailTemplate | Unset = UNSET
+ password_changed: ProjectConfigEmailTemplate | Unset = UNSET
+ welcome: ProjectConfigEmailTemplate | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_email_template import ProjectConfigEmailTemplate
+ confirmation: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.confirmation, Unset):
+ confirmation = self.confirmation.to_dict()
+
+ password_reset: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.password_reset, Unset):
+ password_reset = self.password_reset.to_dict()
+
+ password_changed: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.password_changed, Unset):
+ password_changed = self.password_changed.to_dict()
+
+ welcome: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.welcome, Unset):
+ welcome = self.welcome.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if confirmation is not UNSET:
+ field_dict["confirmation"] = confirmation
+ if password_reset is not UNSET:
+ field_dict["password_reset"] = password_reset
+ if password_changed is not UNSET:
+ field_dict["password_changed"] = password_changed
+ if welcome is not UNSET:
+ field_dict["welcome"] = welcome
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_email_template import ProjectConfigEmailTemplate
+ d = dict(src_dict)
+ _confirmation = d.pop("confirmation", UNSET)
+ confirmation: ProjectConfigEmailTemplate | Unset
+ if isinstance(_confirmation, Unset):
+ confirmation = UNSET
+ else:
+ confirmation = ProjectConfigEmailTemplate.from_dict(_confirmation)
+
+
+
+
+ _password_reset = d.pop("password_reset", UNSET)
+ password_reset: ProjectConfigEmailTemplate | Unset
+ if isinstance(_password_reset, Unset):
+ password_reset = UNSET
+ else:
+ password_reset = ProjectConfigEmailTemplate.from_dict(_password_reset)
+
+
+
+
+ _password_changed = d.pop("password_changed", UNSET)
+ password_changed: ProjectConfigEmailTemplate | Unset
+ if isinstance(_password_changed, Unset):
+ password_changed = UNSET
+ else:
+ password_changed = ProjectConfigEmailTemplate.from_dict(_password_changed)
+
+
+
+
+ _welcome = d.pop("welcome", UNSET)
+ welcome: ProjectConfigEmailTemplate | Unset
+ if isinstance(_welcome, Unset):
+ welcome = UNSET
+ else:
+ welcome = ProjectConfigEmailTemplate.from_dict(_welcome)
+
+
+
+
+ project_config_email_templates = cls(
+ confirmation=confirmation,
+ password_reset=password_reset,
+ password_changed=password_changed,
+ welcome=welcome,
+ )
+
+ return project_config_email_templates
+
diff --git a/src/volcano_sdk/_generated/models/project_config_frontend.py b/src/volcano_sdk/_generated/models/project_config_frontend.py
new file mode 100644
index 00000000..f4ae1e83
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_frontend.py
@@ -0,0 +1,91 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_custom_domain import ProjectConfigCustomDomain
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigFrontend")
+
+
+
+@_attrs_define
+class ProjectConfigFrontend:
+ """ Configuration for an existing (deployed) frontend. Frontends are never
+ created or deleted through the manifest. A declared frontend entry
+ without `custom_domain` deletes an existing custom domain.
+
+ Attributes:
+ name (str):
+ custom_domain (ProjectConfigCustomDomain | Unset): Custom domain with BYOC TLS (PRO plan). `tls` is required
+ when the
+ domain is first created and optional afterwards: providing new TLS
+ material for the same domain rotates the certificate in place (zero
+ downtime); omitting `tls` keeps the stored certificate. TLS material is
+ write-only and omitted from config export.
+ """
+
+ name: str
+ custom_domain: ProjectConfigCustomDomain | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_custom_domain import ProjectConfigCustomDomain
+ name = self.name
+
+ custom_domain: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.custom_domain, Unset):
+ custom_domain = self.custom_domain.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "name": name,
+ })
+ if custom_domain is not UNSET:
+ field_dict["custom_domain"] = custom_domain
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_custom_domain import ProjectConfigCustomDomain
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ _custom_domain = d.pop("custom_domain", UNSET)
+ custom_domain: ProjectConfigCustomDomain | Unset
+ if isinstance(_custom_domain, Unset):
+ custom_domain = UNSET
+ else:
+ custom_domain = ProjectConfigCustomDomain.from_dict(_custom_domain)
+
+
+
+
+ project_config_frontend = cls(
+ name=name,
+ custom_domain=custom_domain,
+ )
+
+ return project_config_frontend
+
diff --git a/src/volcano_sdk/_generated/models/project_config_function.py b/src/volcano_sdk/_generated/models/project_config_function.py
new file mode 100644
index 00000000..92fed310
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_function.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_scheduler import ProjectConfigScheduler
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigFunction")
+
+
+
+@_attrs_define
+class ProjectConfigFunction:
+ """ Configuration for an existing (deployed) function. Functions are never
+ created or deleted through the manifest. When `schedulers` is declared
+ it is fully synced (schedulers absent from the list are deleted);
+ omitting `schedulers` leaves the function's schedulers untouched.
+
+ Attributes:
+ name (str):
+ public (bool | Unset): Function visibility for anon-key invocation
+ schedulers (list[ProjectConfigScheduler] | Unset):
+ """
+
+ name: str
+ public: bool | Unset = UNSET
+ schedulers: list[ProjectConfigScheduler] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_scheduler import ProjectConfigScheduler
+ name = self.name
+
+ public = self.public
+
+ schedulers: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.schedulers, Unset):
+ schedulers = []
+ for schedulers_item_data in self.schedulers:
+ schedulers_item = schedulers_item_data.to_dict()
+ schedulers.append(schedulers_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "name": name,
+ })
+ if public is not UNSET:
+ field_dict["public"] = public
+ if schedulers is not UNSET:
+ field_dict["schedulers"] = schedulers
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_scheduler import ProjectConfigScheduler
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ public = d.pop("public", UNSET)
+
+ _schedulers = d.pop("schedulers", UNSET)
+ schedulers: list[ProjectConfigScheduler] | Unset = UNSET
+ if _schedulers is not UNSET:
+ schedulers = []
+ for schedulers_item_data in _schedulers:
+ schedulers_item = ProjectConfigScheduler.from_dict(schedulers_item_data)
+
+
+
+ schedulers.append(schedulers_item)
+
+
+ project_config_function = cls(
+ name=name,
+ public=public,
+ schedulers=schedulers,
+ )
+
+ return project_config_function
+
diff --git a/src/volcano_sdk/_generated/models/project_config_hosted_page.py b/src/volcano_sdk/_generated/models/project_config_hosted_page.py
new file mode 100644
index 00000000..845ad0cc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_hosted_page.py
@@ -0,0 +1,68 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigHostedPage")
+
+
+
+@_attrs_define
+class ProjectConfigHostedPage:
+ """
+ Attributes:
+ html (str): Raw HTML markup for the page. Max 256 KiB.
+ css (str | Unset): Optional CSS injected at render time. Max 256 KiB.
+ """
+
+ html: str
+ css: str | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ html = self.html
+
+ css = self.css
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "html": html,
+ })
+ if css is not UNSET:
+ field_dict["css"] = css
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ html = d.pop("html")
+
+ css = d.pop("css", UNSET)
+
+ project_config_hosted_page = cls(
+ html=html,
+ css=css,
+ )
+
+ return project_config_hosted_page
+
diff --git a/src/volcano_sdk/_generated/models/project_config_hosted_pages.py b/src/volcano_sdk/_generated/models/project_config_hosted_pages.py
new file mode 100644
index 00000000..3ed7465e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_hosted_pages.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_hosted_page import ProjectConfigHostedPage
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigHostedPages")
+
+
+
+@_attrs_define
+class ProjectConfigHostedPages:
+ """ Hosted auth pages keyed by page type (PRO plan). Upsert-only: omitted
+ pages are left untouched (there is no delete for hosted pages).
+
+ Attributes:
+ login (ProjectConfigHostedPage | Unset):
+ reset_password (ProjectConfigHostedPage | Unset):
+ """
+
+ login: ProjectConfigHostedPage | Unset = UNSET
+ reset_password: ProjectConfigHostedPage | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_hosted_page import ProjectConfigHostedPage
+ login: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.login, Unset):
+ login = self.login.to_dict()
+
+ reset_password: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.reset_password, Unset):
+ reset_password = self.reset_password.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if login is not UNSET:
+ field_dict["login"] = login
+ if reset_password is not UNSET:
+ field_dict["reset_password"] = reset_password
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_hosted_page import ProjectConfigHostedPage
+ d = dict(src_dict)
+ _login = d.pop("login", UNSET)
+ login: ProjectConfigHostedPage | Unset
+ if isinstance(_login, Unset):
+ login = UNSET
+ else:
+ login = ProjectConfigHostedPage.from_dict(_login)
+
+
+
+
+ _reset_password = d.pop("reset_password", UNSET)
+ reset_password: ProjectConfigHostedPage | Unset
+ if isinstance(_reset_password, Unset):
+ reset_password = UNSET
+ else:
+ reset_password = ProjectConfigHostedPage.from_dict(_reset_password)
+
+
+
+
+ project_config_hosted_pages = cls(
+ login=login,
+ reset_password=reset_password,
+ )
+
+ return project_config_hosted_pages
+
diff --git a/src/volcano_sdk/_generated/models/project_config_missing_resource.py b/src/volcano_sdk/_generated/models/project_config_missing_resource.py
new file mode 100644
index 00000000..5f3af3b3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_missing_resource.py
@@ -0,0 +1,90 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_missing_resource_type import check_project_config_missing_resource_type
+from ..models.project_config_missing_resource_type import ProjectConfigMissingResourceType
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigMissingResource")
+
+
+
+@_attrs_define
+class ProjectConfigMissingResource:
+ """
+ Attributes:
+ type_ (ProjectConfigMissingResourceType):
+ name (str):
+ """
+
+ type_: ProjectConfigMissingResourceType
+ name: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ type_: str = self.type_
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "type": type_,
+ "name": name,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ type_ = check_project_config_missing_resource_type(d.pop("type"))
+
+
+
+
+ name = d.pop("name")
+
+ project_config_missing_resource = cls(
+ type_=type_,
+ name=name,
+ )
+
+
+ project_config_missing_resource.additional_properties = d
+ return project_config_missing_resource
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_missing_resource_type.py b/src/volcano_sdk/_generated/models/project_config_missing_resource_type.py
new file mode 100644
index 00000000..d7ed1a79
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_missing_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigMissingResourceType = Literal['bucket', 'database', 'frontend', 'function']
+
+PROJECT_CONFIG_MISSING_RESOURCE_TYPE_VALUES: set[ProjectConfigMissingResourceType] = { 'bucket', 'database', 'frontend', 'function', }
+
+def check_project_config_missing_resource_type(value: str) -> ProjectConfigMissingResourceType:
+ if value in PROJECT_CONFIG_MISSING_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_MISSING_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_o_auth_provider.py b/src/volcano_sdk/_generated/models/project_config_o_auth_provider.py
new file mode 100644
index 00000000..01994002
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_o_auth_provider.py
@@ -0,0 +1,116 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_o_auth_provider_provider import check_project_config_o_auth_provider_provider
+from ..models.project_config_o_auth_provider_provider import ProjectConfigOAuthProviderProvider
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigOAuthProvider")
+
+
+
+@_attrs_define
+class ProjectConfigOAuthProvider:
+ """
+ Attributes:
+ provider (ProjectConfigOAuthProviderProvider):
+ enabled (bool | Unset):
+ client_id (str | Unset): Required for non-device providers. Server-generated for
+ `provider=device` (exported read-only, ignored on apply).
+ client_secret (str | Unset): Write-only; omitted from config export. Not used for `provider=device`.
+ redirect_url (str | Unset): Not used for `provider=device`.
+ scopes (list[str] | Unset):
+ """
+
+ provider: ProjectConfigOAuthProviderProvider
+ enabled: bool | Unset = UNSET
+ client_id: str | Unset = UNSET
+ client_secret: str | Unset = UNSET
+ redirect_url: str | Unset = UNSET
+ scopes: list[str] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ provider: str = self.provider
+
+ enabled = self.enabled
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ redirect_url = self.redirect_url
+
+ scopes: list[str] | Unset = UNSET
+ if not isinstance(self.scopes, Unset):
+ scopes = self.scopes
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "provider": provider,
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if client_id is not UNSET:
+ field_dict["client_id"] = client_id
+ if client_secret is not UNSET:
+ field_dict["client_secret"] = client_secret
+ if redirect_url is not UNSET:
+ field_dict["redirect_url"] = redirect_url
+ if scopes is not UNSET:
+ field_dict["scopes"] = scopes
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ provider = check_project_config_o_auth_provider_provider(d.pop("provider"))
+
+
+
+
+ enabled = d.pop("enabled", UNSET)
+
+ client_id = d.pop("client_id", UNSET)
+
+ client_secret = d.pop("client_secret", UNSET)
+
+ redirect_url = d.pop("redirect_url", UNSET)
+
+ scopes = cast(list[str], d.pop("scopes", UNSET))
+
+
+ project_config_o_auth_provider = cls(
+ provider=provider,
+ enabled=enabled,
+ client_id=client_id,
+ client_secret=client_secret,
+ redirect_url=redirect_url,
+ scopes=scopes,
+ )
+
+ return project_config_o_auth_provider
+
diff --git a/src/volcano_sdk/_generated/models/project_config_o_auth_provider_provider.py b/src/volcano_sdk/_generated/models/project_config_o_auth_provider_provider.py
new file mode 100644
index 00000000..c376aa7c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_o_auth_provider_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigOAuthProviderProvider = Literal['apple', 'device', 'github', 'google', 'microsoft']
+
+PROJECT_CONFIG_O_AUTH_PROVIDER_PROVIDER_VALUES: set[ProjectConfigOAuthProviderProvider] = { 'apple', 'device', 'github', 'google', 'microsoft', }
+
+def check_project_config_o_auth_provider_provider(value: str) -> ProjectConfigOAuthProviderProvider:
+ if value in PROJECT_CONFIG_O_AUTH_PROVIDER_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_O_AUTH_PROVIDER_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_project.py b/src/volcano_sdk/_generated/models/project_config_project.py
new file mode 100644
index 00000000..467af698
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_project.py
@@ -0,0 +1,85 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigProject")
+
+
+
+@_attrs_define
+class ProjectConfigProject:
+ """ Project-level settings. `name` renames the project.
+
+ Attributes:
+ name (str | Unset):
+ all_regions (bool | Unset): Region policy. `false` requires `selected_regions` (PRO plan).
+ selected_regions (list[str] | Unset): Region subset (bare region names). Requires `all_regions=false`.
+ """
+
+ name: str | Unset = UNSET
+ all_regions: bool | Unset = UNSET
+ selected_regions: list[str] | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ all_regions = self.all_regions
+
+ selected_regions: list[str] | Unset = UNSET
+ if not isinstance(self.selected_regions, Unset):
+ selected_regions = self.selected_regions
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if name is not UNSET:
+ field_dict["name"] = name
+ if all_regions is not UNSET:
+ field_dict["all_regions"] = all_regions
+ if selected_regions is not UNSET:
+ field_dict["selected_regions"] = selected_regions
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name", UNSET)
+
+ all_regions = d.pop("all_regions", UNSET)
+
+ selected_regions = cast(list[str], d.pop("selected_regions", UNSET))
+
+
+ project_config_project = cls(
+ name=name,
+ all_regions=all_regions,
+ selected_regions=selected_regions,
+ )
+
+ return project_config_project
+
diff --git a/src/volcano_sdk/_generated/models/project_config_realtime.py b/src/volcano_sdk/_generated/models/project_config_realtime.py
new file mode 100644
index 00000000..58618a5f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_realtime.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigRealtime")
+
+
+
+@_attrs_define
+class ProjectConfigRealtime:
+ """
+ Attributes:
+ enabled (bool | Unset):
+ broadcast_enabled (bool | Unset):
+ presence_enabled (bool | Unset):
+ postgres_changes_enabled (bool | Unset):
+ """
+
+ enabled: bool | Unset = UNSET
+ broadcast_enabled: bool | Unset = UNSET
+ presence_enabled: bool | Unset = UNSET
+ postgres_changes_enabled: bool | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enabled = self.enabled
+
+ broadcast_enabled = self.broadcast_enabled
+
+ presence_enabled = self.presence_enabled
+
+ postgres_changes_enabled = self.postgres_changes_enabled
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if broadcast_enabled is not UNSET:
+ field_dict["broadcast_enabled"] = broadcast_enabled
+ if presence_enabled is not UNSET:
+ field_dict["presence_enabled"] = presence_enabled
+ if postgres_changes_enabled is not UNSET:
+ field_dict["postgres_changes_enabled"] = postgres_changes_enabled
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ broadcast_enabled = d.pop("broadcast_enabled", UNSET)
+
+ presence_enabled = d.pop("presence_enabled", UNSET)
+
+ postgres_changes_enabled = d.pop("postgres_changes_enabled", UNSET)
+
+ project_config_realtime = cls(
+ enabled=enabled,
+ broadcast_enabled=broadcast_enabled,
+ presence_enabled=presence_enabled,
+ postgres_changes_enabled=postgres_changes_enabled,
+ )
+
+ return project_config_realtime
+
diff --git a/src/volcano_sdk/_generated/models/project_config_scheduler.py b/src/volcano_sdk/_generated/models/project_config_scheduler.py
new file mode 100644
index 00000000..0d25cad7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_scheduler.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_scheduler_payload import ProjectConfigSchedulerPayload
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigScheduler")
+
+
+
+@_attrs_define
+class ProjectConfigScheduler:
+ """
+ Attributes:
+ name (str):
+ cron (str): 5-field UTC cron expression
+ enabled (bool | Unset):
+ payload (ProjectConfigSchedulerPayload | Unset):
+ """
+
+ name: str
+ cron: str
+ enabled: bool | Unset = UNSET
+ payload: ProjectConfigSchedulerPayload | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_scheduler_payload import ProjectConfigSchedulerPayload
+ name = self.name
+
+ cron = self.cron
+
+ enabled = self.enabled
+
+ payload: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.payload, Unset):
+ payload = self.payload.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "name": name,
+ "cron": cron,
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if payload is not UNSET:
+ field_dict["payload"] = payload
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_scheduler_payload import ProjectConfigSchedulerPayload
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ cron = d.pop("cron")
+
+ enabled = d.pop("enabled", UNSET)
+
+ _payload = d.pop("payload", UNSET)
+ payload: ProjectConfigSchedulerPayload | Unset
+ if isinstance(_payload, Unset):
+ payload = UNSET
+ else:
+ payload = ProjectConfigSchedulerPayload.from_dict(_payload)
+
+
+
+
+ project_config_scheduler = cls(
+ name=name,
+ cron=cron,
+ enabled=enabled,
+ payload=payload,
+ )
+
+ return project_config_scheduler
+
diff --git a/src/volcano_sdk/_generated/models/project_config_scheduler_payload.py b/src/volcano_sdk/_generated/models/project_config_scheduler_payload.py
new file mode 100644
index 00000000..103fe275
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_scheduler_payload.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigSchedulerPayload")
+
+
+
+@_attrs_define
+class ProjectConfigSchedulerPayload:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ project_config_scheduler_payload = cls(
+ )
+
+
+ project_config_scheduler_payload.additional_properties = d
+ return project_config_scheduler_payload
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_skipped_resource.py b/src/volcano_sdk/_generated/models/project_config_skipped_resource.py
new file mode 100644
index 00000000..297aeda0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_skipped_resource.py
@@ -0,0 +1,98 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_config_skipped_resource_type import check_project_config_skipped_resource_type
+from ..models.project_config_skipped_resource_type import ProjectConfigSkippedResourceType
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigSkippedResource")
+
+
+
+@_attrs_define
+class ProjectConfigSkippedResource:
+ """
+ Attributes:
+ type_ (ProjectConfigSkippedResourceType):
+ name (str):
+ reason (str):
+ """
+
+ type_: ProjectConfigSkippedResourceType
+ name: str
+ reason: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ type_: str = self.type_
+
+ name = self.name
+
+ reason = self.reason
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "type": type_,
+ "name": name,
+ "reason": reason,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ type_ = check_project_config_skipped_resource_type(d.pop("type"))
+
+
+
+
+ name = d.pop("name")
+
+ reason = d.pop("reason")
+
+ project_config_skipped_resource = cls(
+ type_=type_,
+ name=name,
+ reason=reason,
+ )
+
+
+ project_config_skipped_resource.additional_properties = d
+ return project_config_skipped_resource
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_skipped_resource_type.py b/src/volcano_sdk/_generated/models/project_config_skipped_resource_type.py
new file mode 100644
index 00000000..e9a14b4a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_skipped_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigSkippedResourceType = Literal['bucket', 'database', 'frontend', 'function']
+
+PROJECT_CONFIG_SKIPPED_RESOURCE_TYPE_VALUES: set[ProjectConfigSkippedResourceType] = { 'bucket', 'database', 'frontend', 'function', }
+
+def check_project_config_skipped_resource_type(value: str) -> ProjectConfigSkippedResourceType:
+ if value in PROJECT_CONFIG_SKIPPED_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_SKIPPED_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_config_validation_error.py b/src/volcano_sdk/_generated/models/project_config_validation_error.py
new file mode 100644
index 00000000..940d9435
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_validation_error.py
@@ -0,0 +1,94 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigValidationError")
+
+
+
+@_attrs_define
+class ProjectConfigValidationError:
+ """
+ Attributes:
+ section (str): Manifest section the error refers to (e.g. databases, functions).
+ message (str):
+ name (str | Unset): Resource name or key within the section, when applicable.
+ """
+
+ section: str
+ message: str
+ name: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ section = self.section
+
+ message = self.message
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "section": section,
+ "message": message,
+ })
+ if name is not UNSET:
+ field_dict["name"] = name
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ section = d.pop("section")
+
+ message = d.pop("message")
+
+ name = d.pop("name", UNSET)
+
+ project_config_validation_error = cls(
+ section=section,
+ message=message,
+ name=name,
+ )
+
+
+ project_config_validation_error.additional_properties = d
+ return project_config_validation_error
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_validation_error_response.py b/src/volcano_sdk/_generated/models/project_config_validation_error_response.py
new file mode 100644
index 00000000..7ff8a9cf
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_validation_error_response.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_config_validation_error import ProjectConfigValidationError
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigValidationErrorResponse")
+
+
+
+@_attrs_define
+class ProjectConfigValidationErrorResponse:
+ """ Returned when manifest validation fails. Nothing was applied.
+
+ Attributes:
+ error (str):
+ errors (list[ProjectConfigValidationError]):
+ """
+
+ error: str
+ errors: list[ProjectConfigValidationError]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_config_validation_error import ProjectConfigValidationError
+ error = self.error
+
+ errors = []
+ for errors_item_data in self.errors:
+ errors_item = errors_item_data.to_dict()
+ errors.append(errors_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "error": error,
+ "errors": errors,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_config_validation_error import ProjectConfigValidationError
+ d = dict(src_dict)
+ error = d.pop("error")
+
+ errors = []
+ _errors = d.pop("errors")
+ for errors_item_data in (_errors):
+ errors_item = ProjectConfigValidationError.from_dict(errors_item_data)
+
+
+
+ errors.append(errors_item)
+
+
+ project_config_validation_error_response = cls(
+ error=error,
+ errors=errors,
+ )
+
+
+ project_config_validation_error_response.additional_properties = d
+ return project_config_validation_error_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_config_variable.py b/src/volcano_sdk/_generated/models/project_config_variable.py
new file mode 100644
index 00000000..e0fe04f5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_variable.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectConfigVariable")
+
+
+
+@_attrs_define
+class ProjectConfigVariable:
+ """
+ Attributes:
+ name (str):
+ value (str):
+ """
+
+ name: str
+ value: str
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "name": name,
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ value = d.pop("value")
+
+ project_config_variable = cls(
+ name=name,
+ value=value,
+ )
+
+ return project_config_variable
+
diff --git a/src/volcano_sdk/_generated/models/project_config_version.py b/src/volcano_sdk/_generated/models/project_config_version.py
new file mode 100644
index 00000000..e4450d00
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_config_version.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectConfigVersion = Literal[1]
+
+PROJECT_CONFIG_VERSION_VALUES: set[ProjectConfigVersion] = { 1, }
+
+def check_project_config_version(value: int) -> ProjectConfigVersion:
+ if value in PROJECT_CONFIG_VERSION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_CONFIG_VERSION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_deployment.py b/src/volcano_sdk/_generated/models/project_deployment.py
new file mode 100644
index 00000000..584ced1a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_deployment.py
@@ -0,0 +1,231 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_deployment_deploy_source import check_project_deployment_deploy_source
+from ..models.project_deployment_deploy_source import ProjectDeploymentDeploySource
+from ..models.project_deployment_operation import check_project_deployment_operation
+from ..models.project_deployment_operation import ProjectDeploymentOperation
+from ..models.project_deployment_status import check_project_deployment_status
+from ..models.project_deployment_status import ProjectDeploymentStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.deployment_progress import DeploymentProgress
+ from ..models.project_deployment_resource import ProjectDeploymentResource
+
+
+
+
+
+T = TypeVar("T", bound="ProjectDeployment")
+
+
+
+@_attrs_define
+class ProjectDeployment:
+ """ A Function or Frontend deployment attempt in a project-scoped feed.
+
+ Attributes:
+ id (UUID):
+ project_id (UUID):
+ resource (ProjectDeploymentResource): The resource this deployment belongs to.
+ operation (ProjectDeploymentOperation):
+ status (ProjectDeploymentStatus):
+ deploy_source (ProjectDeploymentDeploySource): What initiated this deployment.
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ artifact_version (str | Unset):
+ error_message (str | Unset):
+ completed_at (datetime.datetime | Unset):
+ progress (DeploymentProgress | Unset): Normalized live progress derived from the deployment workflow and build
+ phases.
+ """
+
+ id: UUID
+ project_id: UUID
+ resource: ProjectDeploymentResource
+ operation: ProjectDeploymentOperation
+ status: ProjectDeploymentStatus
+ deploy_source: ProjectDeploymentDeploySource
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ artifact_version: str | Unset = UNSET
+ error_message: str | Unset = UNSET
+ completed_at: datetime.datetime | Unset = UNSET
+ progress: DeploymentProgress | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.deployment_progress import DeploymentProgress
+ from ..models.project_deployment_resource import ProjectDeploymentResource
+ id = str(self.id)
+
+ project_id = str(self.project_id)
+
+ resource = self.resource.to_dict()
+
+ operation: str = self.operation
+
+ status: str = self.status
+
+ deploy_source: str = self.deploy_source
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ artifact_version = self.artifact_version
+
+ error_message = self.error_message
+
+ completed_at: str | Unset = UNSET
+ if not isinstance(self.completed_at, Unset):
+ completed_at = self.completed_at.isoformat()
+
+ progress: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.progress, Unset):
+ progress = self.progress.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "project_id": project_id,
+ "resource": resource,
+ "operation": operation,
+ "status": status,
+ "deploy_source": deploy_source,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if artifact_version is not UNSET:
+ field_dict["artifact_version"] = artifact_version
+ if error_message is not UNSET:
+ field_dict["error_message"] = error_message
+ if completed_at is not UNSET:
+ field_dict["completed_at"] = completed_at
+ if progress is not UNSET:
+ field_dict["progress"] = progress
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.deployment_progress import DeploymentProgress
+ from ..models.project_deployment_resource import ProjectDeploymentResource
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ resource = ProjectDeploymentResource.from_dict(d.pop("resource"))
+
+
+
+
+ operation = check_project_deployment_operation(d.pop("operation"))
+
+
+
+
+ status = check_project_deployment_status(d.pop("status"))
+
+
+
+
+ deploy_source = check_project_deployment_deploy_source(d.pop("deploy_source"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ artifact_version = d.pop("artifact_version", UNSET)
+
+ error_message = d.pop("error_message", UNSET)
+
+ _completed_at = d.pop("completed_at", UNSET)
+ completed_at: datetime.datetime | Unset
+ if isinstance(_completed_at, Unset):
+ completed_at = UNSET
+ else:
+ completed_at = datetime.datetime.fromisoformat(_completed_at)
+
+
+
+
+ _progress = d.pop("progress", UNSET)
+ progress: DeploymentProgress | Unset
+ if isinstance(_progress, Unset):
+ progress = UNSET
+ else:
+ progress = DeploymentProgress.from_dict(_progress)
+
+
+
+
+ project_deployment = cls(
+ id=id,
+ project_id=project_id,
+ resource=resource,
+ operation=operation,
+ status=status,
+ deploy_source=deploy_source,
+ created_at=created_at,
+ updated_at=updated_at,
+ artifact_version=artifact_version,
+ error_message=error_message,
+ completed_at=completed_at,
+ progress=progress,
+ )
+
+
+ project_deployment.additional_properties = d
+ return project_deployment
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_deployment_deploy_source.py b/src/volcano_sdk/_generated/models/project_deployment_deploy_source.py
new file mode 100644
index 00000000..640920a5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_deployment_deploy_source.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectDeploymentDeploySource = Literal['api', 'cli', 'git', 'system', 'unknown', 'web']
+
+PROJECT_DEPLOYMENT_DEPLOY_SOURCE_VALUES: set[ProjectDeploymentDeploySource] = { 'api', 'cli', 'git', 'system', 'unknown', 'web', }
+
+def check_project_deployment_deploy_source(value: str) -> ProjectDeploymentDeploySource:
+ if value in PROJECT_DEPLOYMENT_DEPLOY_SOURCE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_DEPLOYMENT_DEPLOY_SOURCE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_deployment_operation.py b/src/volcano_sdk/_generated/models/project_deployment_operation.py
new file mode 100644
index 00000000..40921462
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_deployment_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectDeploymentOperation = Literal['delete', 'deploy', 'redeploy', 'update']
+
+PROJECT_DEPLOYMENT_OPERATION_VALUES: set[ProjectDeploymentOperation] = { 'delete', 'deploy', 'redeploy', 'update', }
+
+def check_project_deployment_operation(value: str) -> ProjectDeploymentOperation:
+ if value in PROJECT_DEPLOYMENT_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_DEPLOYMENT_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_deployment_resource.py b/src/volcano_sdk/_generated/models/project_deployment_resource.py
new file mode 100644
index 00000000..1e63af55
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_deployment_resource.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_deployment_resource_type import check_project_deployment_resource_type
+from ..models.project_deployment_resource_type import ProjectDeploymentResourceType
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectDeploymentResource")
+
+
+
+@_attrs_define
+class ProjectDeploymentResource:
+ """ The resource this deployment belongs to.
+
+ Attributes:
+ type_ (ProjectDeploymentResourceType):
+ id (UUID):
+ name (str):
+ """
+
+ type_: ProjectDeploymentResourceType
+ id: UUID
+ name: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ type_: str = self.type_
+
+ id = str(self.id)
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "type": type_,
+ "id": id,
+ "name": name,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ type_ = check_project_deployment_resource_type(d.pop("type"))
+
+
+
+
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ project_deployment_resource = cls(
+ type_=type_,
+ id=id,
+ name=name,
+ )
+
+
+ project_deployment_resource.additional_properties = d
+ return project_deployment_resource
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_deployment_resource_type.py b/src/volcano_sdk/_generated/models/project_deployment_resource_type.py
new file mode 100644
index 00000000..c56d0668
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_deployment_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectDeploymentResourceType = Literal['frontend', 'function']
+
+PROJECT_DEPLOYMENT_RESOURCE_TYPE_VALUES: set[ProjectDeploymentResourceType] = { 'frontend', 'function', }
+
+def check_project_deployment_resource_type(value: str) -> ProjectDeploymentResourceType:
+ if value in PROJECT_DEPLOYMENT_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_DEPLOYMENT_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_deployment_status.py b/src/volcano_sdk/_generated/models/project_deployment_status.py
new file mode 100644
index 00000000..d28a97c7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_deployment_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectDeploymentStatus = Literal['active', 'degraded', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded']
+
+PROJECT_DEPLOYMENT_STATUS_VALUES: set[ProjectDeploymentStatus] = { 'active', 'degraded', 'deleted', 'deleting', 'failed', 'provisioning', 'queued', 'superseded', }
+
+def check_project_deployment_status(value: str) -> ProjectDeploymentStatus:
+ if value in PROJECT_DEPLOYMENT_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_DEPLOYMENT_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_deployment_summary.py b/src/volcano_sdk/_generated/models/project_deployment_summary.py
new file mode 100644
index 00000000..03b90a1c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_deployment_summary.py
@@ -0,0 +1,132 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectDeploymentSummary")
+
+
+
+@_attrs_define
+class ProjectDeploymentSummary:
+ """ Aggregate deployment statistics for one resource pipeline.
+
+ Attributes:
+ deployment_count (int): All deployment attempts matching the filters.
+ successful_count (int): Attempts that reached active or deleted.
+ failed_count (int): Attempts that reached failed or degraded.
+ canceled_count (int): Superseded attempts, excluded from success rate and duration.
+ success_rate (float | None): Successful attempts divided by successful plus failed attempts.
+ median_build_duration_seconds (float | None): Median CodeBuild duration across eligible completed attempts.
+ """
+
+ deployment_count: int
+ successful_count: int
+ failed_count: int
+ canceled_count: int
+ success_rate: float | None
+ median_build_duration_seconds: float | None
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ deployment_count = self.deployment_count
+
+ successful_count = self.successful_count
+
+ failed_count = self.failed_count
+
+ canceled_count = self.canceled_count
+
+ success_rate: float | None
+ success_rate = self.success_rate
+
+ median_build_duration_seconds: float | None
+ median_build_duration_seconds = self.median_build_duration_seconds
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "deployment_count": deployment_count,
+ "successful_count": successful_count,
+ "failed_count": failed_count,
+ "canceled_count": canceled_count,
+ "success_rate": success_rate,
+ "median_build_duration_seconds": median_build_duration_seconds,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ deployment_count = d.pop("deployment_count")
+
+ successful_count = d.pop("successful_count")
+
+ failed_count = d.pop("failed_count")
+
+ canceled_count = d.pop("canceled_count")
+
+ def _parse_success_rate(data: object) -> float | None:
+ if data is None:
+ return data
+ return cast(float | None, data)
+
+ success_rate = _parse_success_rate(d.pop("success_rate"))
+
+
+ def _parse_median_build_duration_seconds(data: object) -> float | None:
+ if data is None:
+ return data
+ return cast(float | None, data)
+
+ median_build_duration_seconds = _parse_median_build_duration_seconds(d.pop("median_build_duration_seconds"))
+
+
+ project_deployment_summary = cls(
+ deployment_count=deployment_count,
+ successful_count=successful_count,
+ failed_count=failed_count,
+ canceled_count=canceled_count,
+ success_rate=success_rate,
+ median_build_duration_seconds=median_build_duration_seconds,
+ )
+
+
+ project_deployment_summary.additional_properties = d
+ return project_deployment_summary
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_frontend_custom_domain.py b/src/volcano_sdk/_generated/models/project_frontend_custom_domain.py
new file mode 100644
index 00000000..ccf6585f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_frontend_custom_domain.py
@@ -0,0 +1,218 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.frontend_custom_domain_response_domain_status import check_frontend_custom_domain_response_domain_status
+from ..models.frontend_custom_domain_response_domain_status import FrontendCustomDomainResponseDomainStatus
+from ..models.frontend_custom_domain_response_tls_mode import check_frontend_custom_domain_response_tls_mode
+from ..models.frontend_custom_domain_response_tls_mode import FrontendCustomDomainResponseTlsMode
+from ..models.frontend_custom_domain_response_verification_status import check_frontend_custom_domain_response_verification_status
+from ..models.frontend_custom_domain_response_verification_status import FrontendCustomDomainResponseVerificationStatus
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.frontend_domain_routing_record import FrontendDomainRoutingRecord
+ from ..models.frontend_domain_verification_record import FrontendDomainVerificationRecord
+ from ..models.project_frontend_custom_domain_frontend import ProjectFrontendCustomDomainFrontend
+
+
+
+
+
+T = TypeVar("T", bound="ProjectFrontendCustomDomain")
+
+
+
+@_attrs_define
+class ProjectFrontendCustomDomain:
+ """
+ Attributes:
+ domain (str):
+ tls_mode (FrontendCustomDomainResponseTlsMode):
+ domain_status (FrontendCustomDomainResponseDomainStatus):
+ verification_status (FrontendCustomDomainResponseVerificationStatus):
+ effective_urls (list[str]):
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ frontend (ProjectFrontendCustomDomainFrontend): The frontend this custom domain is attached to. Inlined to
+ avoid a second fetch from the project-scoped feed.
+ verification_records (list[FrontendDomainVerificationRecord] | Unset):
+ required_routing_record (FrontendDomainRoutingRecord | Unset):
+ """
+
+ domain: str
+ tls_mode: FrontendCustomDomainResponseTlsMode
+ domain_status: FrontendCustomDomainResponseDomainStatus
+ verification_status: FrontendCustomDomainResponseVerificationStatus
+ effective_urls: list[str]
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ frontend: ProjectFrontendCustomDomainFrontend
+ verification_records: list[FrontendDomainVerificationRecord] | Unset = UNSET
+ required_routing_record: FrontendDomainRoutingRecord | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend_domain_routing_record import FrontendDomainRoutingRecord
+ from ..models.frontend_domain_verification_record import FrontendDomainVerificationRecord
+ from ..models.project_frontend_custom_domain_frontend import ProjectFrontendCustomDomainFrontend
+ domain = self.domain
+
+ tls_mode: str = self.tls_mode
+
+ domain_status: str = self.domain_status
+
+ verification_status: str = self.verification_status
+
+ effective_urls = self.effective_urls
+
+
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ frontend = self.frontend.to_dict()
+
+ verification_records: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.verification_records, Unset):
+ verification_records = []
+ for verification_records_item_data in self.verification_records:
+ verification_records_item = verification_records_item_data.to_dict()
+ verification_records.append(verification_records_item)
+
+
+
+ required_routing_record: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.required_routing_record, Unset):
+ required_routing_record = self.required_routing_record.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "domain": domain,
+ "tls_mode": tls_mode,
+ "domain_status": domain_status,
+ "verification_status": verification_status,
+ "effective_urls": effective_urls,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ "frontend": frontend,
+ })
+ if verification_records is not UNSET:
+ field_dict["verification_records"] = verification_records
+ if required_routing_record is not UNSET:
+ field_dict["required_routing_record"] = required_routing_record
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend_domain_routing_record import FrontendDomainRoutingRecord
+ from ..models.frontend_domain_verification_record import FrontendDomainVerificationRecord
+ from ..models.project_frontend_custom_domain_frontend import ProjectFrontendCustomDomainFrontend
+ d = dict(src_dict)
+ domain = d.pop("domain")
+
+ tls_mode = check_frontend_custom_domain_response_tls_mode(d.pop("tls_mode"))
+
+
+
+
+ domain_status = check_frontend_custom_domain_response_domain_status(d.pop("domain_status"))
+
+
+
+
+ verification_status = check_frontend_custom_domain_response_verification_status(d.pop("verification_status"))
+
+
+
+
+ effective_urls = cast(list[str], d.pop("effective_urls"))
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ frontend = ProjectFrontendCustomDomainFrontend.from_dict(d.pop("frontend"))
+
+
+
+
+ _verification_records = d.pop("verification_records", UNSET)
+ verification_records: list[FrontendDomainVerificationRecord] | Unset = UNSET
+ if _verification_records is not UNSET:
+ verification_records = []
+ for verification_records_item_data in _verification_records:
+ verification_records_item = FrontendDomainVerificationRecord.from_dict(verification_records_item_data)
+
+
+
+ verification_records.append(verification_records_item)
+
+
+ _required_routing_record = d.pop("required_routing_record", UNSET)
+ required_routing_record: FrontendDomainRoutingRecord | Unset
+ if isinstance(_required_routing_record, Unset):
+ required_routing_record = UNSET
+ else:
+ required_routing_record = FrontendDomainRoutingRecord.from_dict(_required_routing_record)
+
+
+
+
+ project_frontend_custom_domain = cls(
+ domain=domain,
+ tls_mode=tls_mode,
+ domain_status=domain_status,
+ verification_status=verification_status,
+ effective_urls=effective_urls,
+ created_at=created_at,
+ updated_at=updated_at,
+ frontend=frontend,
+ verification_records=verification_records,
+ required_routing_record=required_routing_record,
+ )
+
+
+ project_frontend_custom_domain.additional_properties = d
+ return project_frontend_custom_domain
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_frontend_custom_domain_frontend.py b/src/volcano_sdk/_generated/models/project_frontend_custom_domain_frontend.py
new file mode 100644
index 00000000..5d2f4170
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_frontend_custom_domain_frontend.py
@@ -0,0 +1,90 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectFrontendCustomDomainFrontend")
+
+
+
+@_attrs_define
+class ProjectFrontendCustomDomainFrontend:
+ """ The frontend this custom domain is attached to. Inlined to
+ avoid a second fetch from the project-scoped feed.
+
+ Attributes:
+ id (UUID):
+ name (str):
+ """
+
+ id: UUID
+ name: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ project_frontend_custom_domain_frontend = cls(
+ id=id,
+ name=name,
+ )
+
+
+ project_frontend_custom_domain_frontend.additional_properties = d
+ return project_frontend_custom_domain_frontend
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_git_connection.py b/src/volcano_sdk/_generated/models/project_git_connection.py
new file mode 100644
index 00000000..679d5046
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_git_connection.py
@@ -0,0 +1,122 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectGitConnection")
+
+
+
+@_attrs_define
+class ProjectGitConnection:
+ """
+ Attributes:
+ repo_installation_id (int):
+ repo_id (int): Stable GitHub repository id (repository.id), the authoritative binding.
+ repo_full_name (str):
+ root_directory (str):
+ production_branch (str): The branch a push must land on to deploy. Follows the repository's GitHub default
+ branch unless the project set its own, which a default-branch rename on GitHub then leaves alone.
+ updated_at (datetime.datetime):
+ """
+
+ repo_installation_id: int
+ repo_id: int
+ repo_full_name: str
+ root_directory: str
+ production_branch: str
+ updated_at: datetime.datetime
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ repo_installation_id = self.repo_installation_id
+
+ repo_id = self.repo_id
+
+ repo_full_name = self.repo_full_name
+
+ root_directory = self.root_directory
+
+ production_branch = self.production_branch
+
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "repo_installation_id": repo_installation_id,
+ "repo_id": repo_id,
+ "repo_full_name": repo_full_name,
+ "root_directory": root_directory,
+ "production_branch": production_branch,
+ "updated_at": updated_at,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ repo_installation_id = d.pop("repo_installation_id")
+
+ repo_id = d.pop("repo_id")
+
+ repo_full_name = d.pop("repo_full_name")
+
+ root_directory = d.pop("root_directory")
+
+ production_branch = d.pop("production_branch")
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ project_git_connection = cls(
+ repo_installation_id=repo_installation_id,
+ repo_id=repo_id,
+ repo_full_name=repo_full_name,
+ root_directory=root_directory,
+ production_branch=production_branch,
+ updated_at=updated_at,
+ )
+
+
+ project_git_connection.additional_properties = d
+ return project_git_connection
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_git_deploy_settings.py b/src/volcano_sdk/_generated/models/project_git_deploy_settings.py
new file mode 100644
index 00000000..33b56aff
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_git_deploy_settings.py
@@ -0,0 +1,119 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectGitDeploySettings")
+
+
+
+@_attrs_define
+class ProjectGitDeploySettings:
+ """ A project's GitHub auto-deploy settings: what a push to the connected repo's production branch deploys. All settings
+ are default-off.
+
+ Attributes:
+ auto_deploy_enabled (bool): Whether a production-branch push triggers a deployment.
+ deploy_functions (bool): Whether the repo's functions are deployed on push.
+ updated_at (datetime.datetime):
+ frontend_name (str | Unset): Name of the frontend to build and deploy on push. Omitted when no frontend is
+ deployed. Resolved at deploy time; need not exist yet.
+ frontend_app_root (str | Unset): App root (subdirectory) the frontend builds from. Omitted for the repo root.
+ """
+
+ auto_deploy_enabled: bool
+ deploy_functions: bool
+ updated_at: datetime.datetime
+ frontend_name: str | Unset = UNSET
+ frontend_app_root: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ auto_deploy_enabled = self.auto_deploy_enabled
+
+ deploy_functions = self.deploy_functions
+
+ updated_at = self.updated_at.isoformat()
+
+ frontend_name = self.frontend_name
+
+ frontend_app_root = self.frontend_app_root
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "auto_deploy_enabled": auto_deploy_enabled,
+ "deploy_functions": deploy_functions,
+ "updated_at": updated_at,
+ })
+ if frontend_name is not UNSET:
+ field_dict["frontend_name"] = frontend_name
+ if frontend_app_root is not UNSET:
+ field_dict["frontend_app_root"] = frontend_app_root
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auto_deploy_enabled = d.pop("auto_deploy_enabled")
+
+ deploy_functions = d.pop("deploy_functions")
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ frontend_name = d.pop("frontend_name", UNSET)
+
+ frontend_app_root = d.pop("frontend_app_root", UNSET)
+
+ project_git_deploy_settings = cls(
+ auto_deploy_enabled=auto_deploy_enabled,
+ deploy_functions=deploy_functions,
+ updated_at=updated_at,
+ frontend_name=frontend_name,
+ frontend_app_root=frontend_app_root,
+ )
+
+
+ project_git_deploy_settings.additional_properties = d
+ return project_git_deploy_settings
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_health_category.py b/src/volcano_sdk/_generated/models/project_health_category.py
new file mode 100644
index 00000000..893af8f0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_category.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectHealthCategory = Literal['lifecycle', 'storage']
+
+PROJECT_HEALTH_CATEGORY_VALUES: set[ProjectHealthCategory] = { 'lifecycle', 'storage', }
+
+def check_project_health_category(value: str) -> ProjectHealthCategory:
+ if value in PROJECT_HEALTH_CATEGORY_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_HEALTH_CATEGORY_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_health_check.py b/src/volcano_sdk/_generated/models/project_health_check.py
new file mode 100644
index 00000000..ba1e3a6f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_check.py
@@ -0,0 +1,140 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_health_category import check_project_health_category
+from ..models.project_health_category import ProjectHealthCategory
+from ..models.project_health_status import check_project_health_status
+from ..models.project_health_status import ProjectHealthStatus
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_health_evidence import ProjectHealthEvidence
+ from ..models.project_health_scope import ProjectHealthScope
+
+
+
+
+
+T = TypeVar("T", bound="ProjectHealthCheck")
+
+
+
+@_attrs_define
+class ProjectHealthCheck:
+ """
+ Attributes:
+ id (str):
+ category (ProjectHealthCategory):
+ status (ProjectHealthStatus):
+ reason_code (str):
+ scope (ProjectHealthScope):
+ evidence (ProjectHealthEvidence):
+ """
+
+ id: str
+ category: ProjectHealthCategory
+ status: ProjectHealthStatus
+ reason_code: str
+ scope: ProjectHealthScope
+ evidence: ProjectHealthEvidence
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_health_evidence import ProjectHealthEvidence
+ from ..models.project_health_scope import ProjectHealthScope
+ id = self.id
+
+ category: str = self.category
+
+ status: str = self.status
+
+ reason_code = self.reason_code
+
+ scope = self.scope.to_dict()
+
+ evidence = self.evidence.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "category": category,
+ "status": status,
+ "reason_code": reason_code,
+ "scope": scope,
+ "evidence": evidence,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_health_evidence import ProjectHealthEvidence
+ from ..models.project_health_scope import ProjectHealthScope
+ d = dict(src_dict)
+ id = d.pop("id")
+
+ category = check_project_health_category(d.pop("category"))
+
+
+
+
+ status = check_project_health_status(d.pop("status"))
+
+
+
+
+ reason_code = d.pop("reason_code")
+
+ scope = ProjectHealthScope.from_dict(d.pop("scope"))
+
+
+
+
+ evidence = ProjectHealthEvidence.from_dict(d.pop("evidence"))
+
+
+
+
+ project_health_check = cls(
+ id=id,
+ category=category,
+ status=status,
+ reason_code=reason_code,
+ scope=scope,
+ evidence=evidence,
+ )
+
+
+ project_health_check.additional_properties = d
+ return project_health_check
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_health_data_status.py b/src/volcano_sdk/_generated/models/project_health_data_status.py
new file mode 100644
index 00000000..c02996d5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_data_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectHealthDataStatus = Literal['complete', 'no_data', 'partial', 'stale']
+
+PROJECT_HEALTH_DATA_STATUS_VALUES: set[ProjectHealthDataStatus] = { 'complete', 'no_data', 'partial', 'stale', }
+
+def check_project_health_data_status(value: str) -> ProjectHealthDataStatus:
+ if value in PROJECT_HEALTH_DATA_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_HEALTH_DATA_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_health_evidence.py b/src/volcano_sdk/_generated/models/project_health_evidence.py
new file mode 100644
index 00000000..bc33458f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_evidence.py
@@ -0,0 +1,100 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectHealthEvidence")
+
+
+
+@_attrs_define
+class ProjectHealthEvidence:
+ """
+ Attributes:
+ metric (str):
+ value (float):
+ unit (str):
+ sample_count (int):
+ """
+
+ metric: str
+ value: float
+ unit: str
+ sample_count: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ metric = self.metric
+
+ value = self.value
+
+ unit = self.unit
+
+ sample_count = self.sample_count
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "metric": metric,
+ "value": value,
+ "unit": unit,
+ "sample_count": sample_count,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ metric = d.pop("metric")
+
+ value = d.pop("value")
+
+ unit = d.pop("unit")
+
+ sample_count = d.pop("sample_count")
+
+ project_health_evidence = cls(
+ metric=metric,
+ value=value,
+ unit=unit,
+ sample_count=sample_count,
+ )
+
+
+ project_health_evidence.additional_properties = d
+ return project_health_evidence
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_health_resource.py b/src/volcano_sdk/_generated/models/project_health_resource.py
new file mode 100644
index 00000000..875ca6e8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_resource.py
@@ -0,0 +1,102 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_health_resource_type import check_project_health_resource_type
+from ..models.project_health_resource_type import ProjectHealthResourceType
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectHealthResource")
+
+
+
+@_attrs_define
+class ProjectHealthResource:
+ """
+ Attributes:
+ type_ (ProjectHealthResourceType):
+ id (UUID):
+ name (str):
+ """
+
+ type_: ProjectHealthResourceType
+ id: UUID
+ name: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ type_: str = self.type_
+
+ id = str(self.id)
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "type": type_,
+ "id": id,
+ "name": name,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ type_ = check_project_health_resource_type(d.pop("type"))
+
+
+
+
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ project_health_resource = cls(
+ type_=type_,
+ id=id,
+ name=name,
+ )
+
+
+ project_health_resource.additional_properties = d
+ return project_health_resource
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_health_resource_type.py b/src/volcano_sdk/_generated/models/project_health_resource_type.py
new file mode 100644
index 00000000..89cf9f74
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectHealthResourceType = Literal['database', 'frontend', 'function', 'project']
+
+PROJECT_HEALTH_RESOURCE_TYPE_VALUES: set[ProjectHealthResourceType] = { 'database', 'frontend', 'function', 'project', }
+
+def check_project_health_resource_type(value: str) -> ProjectHealthResourceType:
+ if value in PROJECT_HEALTH_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_HEALTH_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_health_response.py b/src/volcano_sdk/_generated/models/project_health_response.py
new file mode 100644
index 00000000..2fa87321
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_response.py
@@ -0,0 +1,176 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_health_data_status import check_project_health_data_status
+from ..models.project_health_data_status import ProjectHealthDataStatus
+from ..models.project_health_status import check_project_health_status
+from ..models.project_health_status import ProjectHealthStatus
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.project_health_check import ProjectHealthCheck
+
+
+
+
+
+T = TypeVar("T", bound="ProjectHealthResponse")
+
+
+
+@_attrs_define
+class ProjectHealthResponse:
+ """
+ Attributes:
+ project_id (UUID):
+ status (ProjectHealthStatus):
+ observed_at (datetime.datetime):
+ fresh_through (datetime.datetime):
+ data_status (ProjectHealthDataStatus):
+ checks (list[ProjectHealthCheck]):
+ findings (list[ProjectHealthCheck]): Top findings ordered by severity, then stable check ID.
+ """
+
+ project_id: UUID
+ status: ProjectHealthStatus
+ observed_at: datetime.datetime
+ fresh_through: datetime.datetime
+ data_status: ProjectHealthDataStatus
+ checks: list[ProjectHealthCheck]
+ findings: list[ProjectHealthCheck]
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_health_check import ProjectHealthCheck
+ project_id = str(self.project_id)
+
+ status: str = self.status
+
+ observed_at = self.observed_at.isoformat()
+
+ fresh_through = self.fresh_through.isoformat()
+
+ data_status: str = self.data_status
+
+ checks = []
+ for checks_item_data in self.checks:
+ checks_item = checks_item_data.to_dict()
+ checks.append(checks_item)
+
+
+
+ findings = []
+ for findings_item_data in self.findings:
+ findings_item = findings_item_data.to_dict()
+ findings.append(findings_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "project_id": project_id,
+ "status": status,
+ "observed_at": observed_at,
+ "fresh_through": fresh_through,
+ "data_status": data_status,
+ "checks": checks,
+ "findings": findings,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_health_check import ProjectHealthCheck
+ d = dict(src_dict)
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ status = check_project_health_status(d.pop("status"))
+
+
+
+
+ observed_at = datetime.datetime.fromisoformat(d.pop("observed_at"))
+
+
+
+
+ fresh_through = datetime.datetime.fromisoformat(d.pop("fresh_through"))
+
+
+
+
+ data_status = check_project_health_data_status(d.pop("data_status"))
+
+
+
+
+ checks = []
+ _checks = d.pop("checks")
+ for checks_item_data in (_checks):
+ checks_item = ProjectHealthCheck.from_dict(checks_item_data)
+
+
+
+ checks.append(checks_item)
+
+
+ findings = []
+ _findings = d.pop("findings")
+ for findings_item_data in (_findings):
+ findings_item = ProjectHealthCheck.from_dict(findings_item_data)
+
+
+
+ findings.append(findings_item)
+
+
+ project_health_response = cls(
+ project_id=project_id,
+ status=status,
+ observed_at=observed_at,
+ fresh_through=fresh_through,
+ data_status=data_status,
+ checks=checks,
+ findings=findings,
+ )
+
+
+ project_health_response.additional_properties = d
+ return project_health_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_health_scope.py b/src/volcano_sdk/_generated/models/project_health_scope.py
new file mode 100644
index 00000000..3134680d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_scope.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_health_resource import ProjectHealthResource
+
+
+
+
+
+T = TypeVar("T", bound="ProjectHealthScope")
+
+
+
+@_attrs_define
+class ProjectHealthScope:
+ """
+ Attributes:
+ resource (ProjectHealthResource):
+ """
+
+ resource: ProjectHealthResource
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_health_resource import ProjectHealthResource
+ resource = self.resource.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "resource": resource,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_health_resource import ProjectHealthResource
+ d = dict(src_dict)
+ resource = ProjectHealthResource.from_dict(d.pop("resource"))
+
+
+
+
+ project_health_scope = cls(
+ resource=resource,
+ )
+
+
+ project_health_scope.additional_properties = d
+ return project_health_scope
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_health_status.py b/src/volcano_sdk/_generated/models/project_health_status.py
new file mode 100644
index 00000000..c299dfb9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_health_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectHealthStatus = Literal['critical', 'degraded', 'healthy', 'unknown']
+
+PROJECT_HEALTH_STATUS_VALUES: set[ProjectHealthStatus] = { 'critical', 'degraded', 'healthy', 'unknown', }
+
+def check_project_health_status(value: str) -> ProjectHealthStatus:
+ if value in PROJECT_HEALTH_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_HEALTH_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_action.py b/src/volcano_sdk/_generated/models/project_import_action.py
new file mode 100644
index 00000000..465d11ba
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_action.py
@@ -0,0 +1,110 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_import_action_code import check_project_import_action_code
+from ..models.project_import_action_code import ProjectImportActionCode
+from ..models.project_import_disposition import check_project_import_disposition
+from ..models.project_import_disposition import ProjectImportDisposition
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_import_resource import ProjectImportResource
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportAction")
+
+
+
+@_attrs_define
+class ProjectImportAction:
+ """
+ Attributes:
+ code (ProjectImportActionCode):
+ resource (ProjectImportResource):
+ disposition (ProjectImportDisposition):
+ """
+
+ code: ProjectImportActionCode
+ resource: ProjectImportResource
+ disposition: ProjectImportDisposition
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_import_resource import ProjectImportResource
+ code: str = self.code
+
+ resource = self.resource.to_dict()
+
+ disposition: str = self.disposition
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "code": code,
+ "resource": resource,
+ "disposition": disposition,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_import_resource import ProjectImportResource
+ d = dict(src_dict)
+ code = check_project_import_action_code(d.pop("code"))
+
+
+
+
+ resource = ProjectImportResource.from_dict(d.pop("resource"))
+
+
+
+
+ disposition = check_project_import_disposition(d.pop("disposition"))
+
+
+
+
+ project_import_action = cls(
+ code=code,
+ resource=resource,
+ disposition=disposition,
+ )
+
+
+ project_import_action.additional_properties = d
+ return project_import_action
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_action_code.py b/src/volcano_sdk/_generated/models/project_import_action_code.py
new file mode 100644
index 00000000..1d5a2e0e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_action_code.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportActionCode = Literal['frontend.configure', 'git.connect', 'project.create', 'variable.set']
+
+PROJECT_IMPORT_ACTION_CODE_VALUES: set[ProjectImportActionCode] = { 'frontend.configure', 'git.connect', 'project.create', 'variable.set', }
+
+def check_project_import_action_code(value: str) -> ProjectImportActionCode:
+ if value in PROJECT_IMPORT_ACTION_CODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_ACTION_CODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_destination.py b/src/volcano_sdk/_generated/models/project_import_destination.py
new file mode 100644
index 00000000..479a5e38
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_destination.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_import_destination_mode import check_project_import_destination_mode
+from ..models.project_import_destination_mode import ProjectImportDestinationMode
+from ..models.project_import_target import check_project_import_target
+from ..models.project_import_target import ProjectImportTarget
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportDestination")
+
+
+
+@_attrs_define
+class ProjectImportDestination:
+ """
+ Attributes:
+ mode (ProjectImportDestinationMode):
+ project_name (str):
+ target (ProjectImportTarget):
+ """
+
+ mode: ProjectImportDestinationMode
+ project_name: str
+ target: ProjectImportTarget
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ mode: str = self.mode
+
+ project_name = self.project_name
+
+ target: str = self.target
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "mode": mode,
+ "project_name": project_name,
+ "target": target,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ mode = check_project_import_destination_mode(d.pop("mode"))
+
+
+
+
+ project_name = d.pop("project_name")
+
+ target = check_project_import_target(d.pop("target"))
+
+
+
+
+ project_import_destination = cls(
+ mode=mode,
+ project_name=project_name,
+ target=target,
+ )
+
+
+ project_import_destination.additional_properties = d
+ return project_import_destination
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_destination_mode.py b/src/volcano_sdk/_generated/models/project_import_destination_mode.py
new file mode 100644
index 00000000..48683fb3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_destination_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportDestinationMode = Literal['create']
+
+PROJECT_IMPORT_DESTINATION_MODE_VALUES: set[ProjectImportDestinationMode] = { 'create', }
+
+def check_project_import_destination_mode(value: str) -> ProjectImportDestinationMode:
+ if value in PROJECT_IMPORT_DESTINATION_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_DESTINATION_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_disposition.py b/src/volcano_sdk/_generated/models/project_import_disposition.py
new file mode 100644
index 00000000..1048361d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_disposition.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportDisposition = Literal['automatic', 'deferred', 'manual', 'unsupported']
+
+PROJECT_IMPORT_DISPOSITION_VALUES: set[ProjectImportDisposition] = { 'automatic', 'deferred', 'manual', 'unsupported', }
+
+def check_project_import_disposition(value: str) -> ProjectImportDisposition:
+ if value in PROJECT_IMPORT_DISPOSITION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_DISPOSITION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_finding.py b/src/volcano_sdk/_generated/models/project_import_finding.py
new file mode 100644
index 00000000..8d2a1e7c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_finding.py
@@ -0,0 +1,134 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_import_disposition import check_project_import_disposition
+from ..models.project_import_disposition import ProjectImportDisposition
+from ..models.project_import_impact import check_project_import_impact
+from ..models.project_import_impact import ProjectImportImpact
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_import_resource import ProjectImportResource
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportFinding")
+
+
+
+@_attrs_define
+class ProjectImportFinding:
+ """
+ Attributes:
+ code (str):
+ resource (ProjectImportResource):
+ disposition (ProjectImportDisposition):
+ impact (ProjectImportImpact):
+ message (str):
+ remediation (str):
+ """
+
+ code: str
+ resource: ProjectImportResource
+ disposition: ProjectImportDisposition
+ impact: ProjectImportImpact
+ message: str
+ remediation: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_import_resource import ProjectImportResource
+ code = self.code
+
+ resource = self.resource.to_dict()
+
+ disposition: str = self.disposition
+
+ impact: str = self.impact
+
+ message = self.message
+
+ remediation = self.remediation
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "code": code,
+ "resource": resource,
+ "disposition": disposition,
+ "impact": impact,
+ "message": message,
+ "remediation": remediation,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_import_resource import ProjectImportResource
+ d = dict(src_dict)
+ code = d.pop("code")
+
+ resource = ProjectImportResource.from_dict(d.pop("resource"))
+
+
+
+
+ disposition = check_project_import_disposition(d.pop("disposition"))
+
+
+
+
+ impact = check_project_import_impact(d.pop("impact"))
+
+
+
+
+ message = d.pop("message")
+
+ remediation = d.pop("remediation")
+
+ project_import_finding = cls(
+ code=code,
+ resource=resource,
+ disposition=disposition,
+ impact=impact,
+ message=message,
+ remediation=remediation,
+ )
+
+
+ project_import_finding.additional_properties = d
+ return project_import_finding
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_impact.py b/src/volcano_sdk/_generated/models/project_import_impact.py
new file mode 100644
index 00000000..033abf9f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_impact.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportImpact = Literal['blocking', 'none', 'warning']
+
+PROJECT_IMPORT_IMPACT_VALUES: set[ProjectImportImpact] = { 'blocking', 'none', 'warning', }
+
+def check_project_import_impact(value: str) -> ProjectImportImpact:
+ if value in PROJECT_IMPORT_IMPACT_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_IMPACT_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_preflight_request.py b/src/volcano_sdk/_generated/models/project_import_preflight_request.py
new file mode 100644
index 00000000..4b549815
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_preflight_request.py
@@ -0,0 +1,123 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_import_target import check_project_import_target
+from ..models.project_import_target import ProjectImportTarget
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportPreflightRequest")
+
+
+
+@_attrs_define
+class ProjectImportPreflightRequest:
+ """
+ Attributes:
+ connection_id (UUID):
+ source_id (str):
+ project_name (str):
+ target (ProjectImportTarget):
+ confirm_environment_variable_read (bool | Unset): Set to true only after the user confirms an immediately
+ preceding disclosure that the Vercel Integration grant permits reads and writes, while this preflight reads
+ production variable values only. When false or omitted, preflight reads variable metadata only and reports
+ readable values as manual input. Default: False.
+ """
+
+ connection_id: UUID
+ source_id: str
+ project_name: str
+ target: ProjectImportTarget
+ confirm_environment_variable_read: bool | Unset = False
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ connection_id = str(self.connection_id)
+
+ source_id = self.source_id
+
+ project_name = self.project_name
+
+ target: str = self.target
+
+ confirm_environment_variable_read = self.confirm_environment_variable_read
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "connection_id": connection_id,
+ "source_id": source_id,
+ "project_name": project_name,
+ "target": target,
+ })
+ if confirm_environment_variable_read is not UNSET:
+ field_dict["confirm_environment_variable_read"] = confirm_environment_variable_read
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ connection_id = UUID(d.pop("connection_id"))
+
+
+
+
+ source_id = d.pop("source_id")
+
+ project_name = d.pop("project_name")
+
+ target = check_project_import_target(d.pop("target"))
+
+
+
+
+ confirm_environment_variable_read = d.pop("confirm_environment_variable_read", UNSET)
+
+ project_import_preflight_request = cls(
+ connection_id=connection_id,
+ source_id=source_id,
+ project_name=project_name,
+ target=target,
+ confirm_environment_variable_read=confirm_environment_variable_read,
+ )
+
+
+ project_import_preflight_request.additional_properties = d
+ return project_import_preflight_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_readiness.py b/src/volcano_sdk/_generated/models/project_import_readiness.py
new file mode 100644
index 00000000..4a6043d9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_readiness.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportReadiness = Literal['blocked', 'importable', 'needs_input']
+
+PROJECT_IMPORT_READINESS_VALUES: set[ProjectImportReadiness] = { 'blocked', 'importable', 'needs_input', }
+
+def check_project_import_readiness(value: str) -> ProjectImportReadiness:
+ if value in PROJECT_IMPORT_READINESS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_READINESS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_report.py b/src/volcano_sdk/_generated/models/project_import_report.py
new file mode 100644
index 00000000..386b9cfe
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_report.py
@@ -0,0 +1,230 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.import_provider import check_import_provider
+from ..models.import_provider import ImportProvider
+from ..models.project_import_readiness import check_project_import_readiness
+from ..models.project_import_readiness import ProjectImportReadiness
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.import_source import ImportSource
+ from ..models.project_import_action import ProjectImportAction
+ from ..models.project_import_destination import ProjectImportDestination
+ from ..models.project_import_finding import ProjectImportFinding
+ from ..models.project_import_summary import ProjectImportSummary
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportReport")
+
+
+
+@_attrs_define
+class ProjectImportReport:
+ """
+ Attributes:
+ schema_version (str):
+ provider (ImportProvider):
+ source (ImportSource):
+ destination (ProjectImportDestination):
+ actions (list[ProjectImportAction]):
+ findings (list[ProjectImportFinding]):
+ summary (ProjectImportSummary):
+ readiness (ProjectImportReadiness):
+ source_fingerprint (str):
+ capability_fingerprint (str):
+ fingerprint (str):
+ generated_at (datetime.datetime):
+ """
+
+ schema_version: str
+ provider: ImportProvider
+ source: ImportSource
+ destination: ProjectImportDestination
+ actions: list[ProjectImportAction]
+ findings: list[ProjectImportFinding]
+ summary: ProjectImportSummary
+ readiness: ProjectImportReadiness
+ source_fingerprint: str
+ capability_fingerprint: str
+ fingerprint: str
+ generated_at: datetime.datetime
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.import_source import ImportSource
+ from ..models.project_import_action import ProjectImportAction
+ from ..models.project_import_destination import ProjectImportDestination
+ from ..models.project_import_finding import ProjectImportFinding
+ from ..models.project_import_summary import ProjectImportSummary
+ schema_version = self.schema_version
+
+ provider: str = self.provider
+
+ source = self.source.to_dict()
+
+ destination = self.destination.to_dict()
+
+ actions = []
+ for actions_item_data in self.actions:
+ actions_item = actions_item_data.to_dict()
+ actions.append(actions_item)
+
+
+
+ findings = []
+ for findings_item_data in self.findings:
+ findings_item = findings_item_data.to_dict()
+ findings.append(findings_item)
+
+
+
+ summary = self.summary.to_dict()
+
+ readiness: str = self.readiness
+
+ source_fingerprint = self.source_fingerprint
+
+ capability_fingerprint = self.capability_fingerprint
+
+ fingerprint = self.fingerprint
+
+ generated_at = self.generated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "schema_version": schema_version,
+ "provider": provider,
+ "source": source,
+ "destination": destination,
+ "actions": actions,
+ "findings": findings,
+ "summary": summary,
+ "readiness": readiness,
+ "source_fingerprint": source_fingerprint,
+ "capability_fingerprint": capability_fingerprint,
+ "fingerprint": fingerprint,
+ "generated_at": generated_at,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.import_source import ImportSource
+ from ..models.project_import_action import ProjectImportAction
+ from ..models.project_import_destination import ProjectImportDestination
+ from ..models.project_import_finding import ProjectImportFinding
+ from ..models.project_import_summary import ProjectImportSummary
+ d = dict(src_dict)
+ schema_version = d.pop("schema_version")
+
+ provider = check_import_provider(d.pop("provider"))
+
+
+
+
+ source = ImportSource.from_dict(d.pop("source"))
+
+
+
+
+ destination = ProjectImportDestination.from_dict(d.pop("destination"))
+
+
+
+
+ actions = []
+ _actions = d.pop("actions")
+ for actions_item_data in (_actions):
+ actions_item = ProjectImportAction.from_dict(actions_item_data)
+
+
+
+ actions.append(actions_item)
+
+
+ findings = []
+ _findings = d.pop("findings")
+ for findings_item_data in (_findings):
+ findings_item = ProjectImportFinding.from_dict(findings_item_data)
+
+
+
+ findings.append(findings_item)
+
+
+ summary = ProjectImportSummary.from_dict(d.pop("summary"))
+
+
+
+
+ readiness = check_project_import_readiness(d.pop("readiness"))
+
+
+
+
+ source_fingerprint = d.pop("source_fingerprint")
+
+ capability_fingerprint = d.pop("capability_fingerprint")
+
+ fingerprint = d.pop("fingerprint")
+
+ generated_at = datetime.datetime.fromisoformat(d.pop("generated_at"))
+
+
+
+
+ project_import_report = cls(
+ schema_version=schema_version,
+ provider=provider,
+ source=source,
+ destination=destination,
+ actions=actions,
+ findings=findings,
+ summary=summary,
+ readiness=readiness,
+ source_fingerprint=source_fingerprint,
+ capability_fingerprint=capability_fingerprint,
+ fingerprint=fingerprint,
+ generated_at=generated_at,
+ )
+
+
+ project_import_report.additional_properties = d
+ return project_import_report
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_resource.py b/src/volcano_sdk/_generated/models/project_import_resource.py
new file mode 100644
index 00000000..7d054ff5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_resource.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_import_resource_kind import check_project_import_resource_kind
+from ..models.project_import_resource_kind import ProjectImportResourceKind
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportResource")
+
+
+
+@_attrs_define
+class ProjectImportResource:
+ """
+ Attributes:
+ kind (ProjectImportResourceKind):
+ name (str):
+ source_id (str | Unset): Stable provider identifier for a scoped source resource.
+ scope (str | Unset): URL-encoded source scope, including target, branch, and custom environment identifiers.
+ """
+
+ kind: ProjectImportResourceKind
+ name: str
+ source_id: str | Unset = UNSET
+ scope: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ kind: str = self.kind
+
+ name = self.name
+
+ source_id = self.source_id
+
+ scope = self.scope
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "kind": kind,
+ "name": name,
+ })
+ if source_id is not UNSET:
+ field_dict["source_id"] = source_id
+ if scope is not UNSET:
+ field_dict["scope"] = scope
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ kind = check_project_import_resource_kind(d.pop("kind"))
+
+
+
+
+ name = d.pop("name")
+
+ source_id = d.pop("source_id", UNSET)
+
+ scope = d.pop("scope", UNSET)
+
+ project_import_resource = cls(
+ kind=kind,
+ name=name,
+ source_id=source_id,
+ scope=scope,
+ )
+
+
+ project_import_resource.additional_properties = d
+ return project_import_resource
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_resource_kind.py b/src/volcano_sdk/_generated/models/project_import_resource_kind.py
new file mode 100644
index 00000000..eb4e1554
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_resource_kind.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportResourceKind = Literal['domain', 'frontend', 'git_repository', 'project', 'variable']
+
+PROJECT_IMPORT_RESOURCE_KIND_VALUES: set[ProjectImportResourceKind] = { 'domain', 'frontend', 'git_repository', 'project', 'variable', }
+
+def check_project_import_resource_kind(value: str) -> ProjectImportResourceKind:
+ if value in PROJECT_IMPORT_RESOURCE_KIND_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_RESOURCE_KIND_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_run.py b/src/volcano_sdk/_generated/models/project_import_run.py
new file mode 100644
index 00000000..d1dfaea2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_run.py
@@ -0,0 +1,190 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.import_provider import check_import_provider
+from ..models.import_provider import ImportProvider
+from ..models.project_import_run_status import check_project_import_run_status
+from ..models.project_import_run_status import ProjectImportRunStatus
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.deployment_reference import DeploymentReference
+ from ..models.resource_reference import ResourceReference
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportRun")
+
+
+
+@_attrs_define
+class ProjectImportRun:
+ """
+ Attributes:
+ id (str):
+ provider (ImportProvider):
+ source_id (str):
+ destination_project_name (str):
+ resource (ResourceReference): Stable reference to a Volcano resource.
+ deployment (DeploymentReference): Stable reference to a Volcano deployment run.
+ status (ProjectImportRunStatus):
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ error_code (str | Unset):
+ error_message (str | Unset):
+ """
+
+ id: str
+ provider: ImportProvider
+ source_id: str
+ destination_project_name: str
+ resource: ResourceReference
+ deployment: DeploymentReference
+ status: ProjectImportRunStatus
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ error_code: str | Unset = UNSET
+ error_message: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.deployment_reference import DeploymentReference
+ from ..models.resource_reference import ResourceReference
+ id = self.id
+
+ provider: str = self.provider
+
+ source_id = self.source_id
+
+ destination_project_name = self.destination_project_name
+
+ resource = self.resource.to_dict()
+
+ deployment = self.deployment.to_dict()
+
+ status: str = self.status
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ error_code = self.error_code
+
+ error_message = self.error_message
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "provider": provider,
+ "source_id": source_id,
+ "destination_project_name": destination_project_name,
+ "resource": resource,
+ "deployment": deployment,
+ "status": status,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if error_code is not UNSET:
+ field_dict["error_code"] = error_code
+ if error_message is not UNSET:
+ field_dict["error_message"] = error_message
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.deployment_reference import DeploymentReference
+ from ..models.resource_reference import ResourceReference
+ d = dict(src_dict)
+ id = d.pop("id")
+
+ provider = check_import_provider(d.pop("provider"))
+
+
+
+
+ source_id = d.pop("source_id")
+
+ destination_project_name = d.pop("destination_project_name")
+
+ resource = ResourceReference.from_dict(d.pop("resource"))
+
+
+
+
+ deployment = DeploymentReference.from_dict(d.pop("deployment"))
+
+
+
+
+ status = check_project_import_run_status(d.pop("status"))
+
+
+
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ error_code = d.pop("error_code", UNSET)
+
+ error_message = d.pop("error_message", UNSET)
+
+ project_import_run = cls(
+ id=id,
+ provider=provider,
+ source_id=source_id,
+ destination_project_name=destination_project_name,
+ resource=resource,
+ deployment=deployment,
+ status=status,
+ created_at=created_at,
+ updated_at=updated_at,
+ error_code=error_code,
+ error_message=error_message,
+ )
+
+
+ project_import_run.additional_properties = d
+ return project_import_run
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_run_status.py b/src/volcano_sdk/_generated/models/project_import_run_status.py
new file mode 100644
index 00000000..550c720c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_run_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportRunStatus = Literal['failed', 'pending', 'running', 'succeeded', 'superseded']
+
+PROJECT_IMPORT_RUN_STATUS_VALUES: set[ProjectImportRunStatus] = { 'failed', 'pending', 'running', 'succeeded', 'superseded', }
+
+def check_project_import_run_status(value: str) -> ProjectImportRunStatus:
+ if value in PROJECT_IMPORT_RUN_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_RUN_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_import_start_request.py b/src/volcano_sdk/_generated/models/project_import_start_request.py
new file mode 100644
index 00000000..547b44f4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_start_request.py
@@ -0,0 +1,126 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_import_target import check_project_import_target
+from ..models.project_import_target import ProjectImportTarget
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportStartRequest")
+
+
+
+@_attrs_define
+class ProjectImportStartRequest:
+ """
+ Attributes:
+ connection_id (UUID):
+ source_id (str):
+ project_name (str):
+ target (ProjectImportTarget):
+ confirm_environment_variable_read (bool):
+ preflight_fingerprint (str):
+ """
+
+ connection_id: UUID
+ source_id: str
+ project_name: str
+ target: ProjectImportTarget
+ confirm_environment_variable_read: bool
+ preflight_fingerprint: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ connection_id = str(self.connection_id)
+
+ source_id = self.source_id
+
+ project_name = self.project_name
+
+ target: str = self.target
+
+ confirm_environment_variable_read = self.confirm_environment_variable_read
+
+ preflight_fingerprint = self.preflight_fingerprint
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "connection_id": connection_id,
+ "source_id": source_id,
+ "project_name": project_name,
+ "target": target,
+ "confirm_environment_variable_read": confirm_environment_variable_read,
+ "preflight_fingerprint": preflight_fingerprint,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ connection_id = UUID(d.pop("connection_id"))
+
+
+
+
+ source_id = d.pop("source_id")
+
+ project_name = d.pop("project_name")
+
+ target = check_project_import_target(d.pop("target"))
+
+
+
+
+ confirm_environment_variable_read = d.pop("confirm_environment_variable_read")
+
+ preflight_fingerprint = d.pop("preflight_fingerprint")
+
+ project_import_start_request = cls(
+ connection_id=connection_id,
+ source_id=source_id,
+ project_name=project_name,
+ target=target,
+ confirm_environment_variable_read=confirm_environment_variable_read,
+ preflight_fingerprint=preflight_fingerprint,
+ )
+
+
+ project_import_start_request.additional_properties = d
+ return project_import_start_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_summary.py b/src/volcano_sdk/_generated/models/project_import_summary.py
new file mode 100644
index 00000000..b3f5525b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_summary.py
@@ -0,0 +1,116 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectImportSummary")
+
+
+
+@_attrs_define
+class ProjectImportSummary:
+ """
+ Attributes:
+ automatic (int):
+ manual (int):
+ deferred (int):
+ unsupported (int):
+ warnings (int):
+ blocking (int):
+ """
+
+ automatic: int
+ manual: int
+ deferred: int
+ unsupported: int
+ warnings: int
+ blocking: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ automatic = self.automatic
+
+ manual = self.manual
+
+ deferred = self.deferred
+
+ unsupported = self.unsupported
+
+ warnings = self.warnings
+
+ blocking = self.blocking
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "automatic": automatic,
+ "manual": manual,
+ "deferred": deferred,
+ "unsupported": unsupported,
+ "warnings": warnings,
+ "blocking": blocking,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ automatic = d.pop("automatic")
+
+ manual = d.pop("manual")
+
+ deferred = d.pop("deferred")
+
+ unsupported = d.pop("unsupported")
+
+ warnings = d.pop("warnings")
+
+ blocking = d.pop("blocking")
+
+ project_import_summary = cls(
+ automatic=automatic,
+ manual=manual,
+ deferred=deferred,
+ unsupported=unsupported,
+ warnings=warnings,
+ blocking=blocking,
+ )
+
+
+ project_import_summary.additional_properties = d
+ return project_import_summary
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_import_target.py b/src/volcano_sdk/_generated/models/project_import_target.py
new file mode 100644
index 00000000..8a86996d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_import_target.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectImportTarget = Literal['production']
+
+PROJECT_IMPORT_TARGET_VALUES: set[ProjectImportTarget] = { 'production', }
+
+def check_project_import_target(value: str) -> ProjectImportTarget:
+ if value in PROJECT_IMPORT_TARGET_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_IMPORT_TARGET_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_lock_lease.py b/src/volcano_sdk/_generated/models/project_lock_lease.py
new file mode 100644
index 00000000..54cd16e2
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_lock_lease.py
@@ -0,0 +1,75 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectLockLease")
+
+
+
+@_attrs_define
+class ProjectLockLease:
+ """
+ Attributes:
+ expires_at (datetime.datetime): Advisory lease expiry timestamp in UTC.
+ fencing_token (int): Monotonically increasing token for this acquisition. It rises whenever the
+ lock changes hands and stays the same across renewals of one lease. Pass it
+ to the resource you are protecting and reject any write carrying a token
+ lower than the highest already seen; that is what stops a displaced holder
+ from writing after its lease lapsed.
+ """
+
+ expires_at: datetime.datetime
+ fencing_token: int
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ expires_at = self.expires_at.isoformat()
+
+ fencing_token = self.fencing_token
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "expires_at": expires_at,
+ "fencing_token": fencing_token,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ expires_at = datetime.datetime.fromisoformat(d.pop("expires_at"))
+
+
+
+
+ fencing_token = d.pop("fencing_token")
+
+ project_lock_lease = cls(
+ expires_at=expires_at,
+ fencing_token=fencing_token,
+ )
+
+ return project_lock_lease
+
diff --git a/src/volcano_sdk/_generated/models/project_lock_lease_request.py b/src/volcano_sdk/_generated/models/project_lock_lease_request.py
new file mode 100644
index 00000000..5b399d03
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_lock_lease_request.py
@@ -0,0 +1,62 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectLockLeaseRequest")
+
+
+
+@_attrs_define
+class ProjectLockLeaseRequest:
+ """
+ Attributes:
+ ttl_seconds (int): Lease duration in seconds, from 5 seconds through 90 days, measured
+ from when the request is served. Renew before it elapses. A renewal
+ sets the new expiry outright, so a shorter TTL shortens the lease.
+ Renewals cannot extend an acquisition beyond its absolute 90-day
+ deadline.
+ """
+
+ ttl_seconds: int
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ ttl_seconds = self.ttl_seconds
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "ttl_seconds": ttl_seconds,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ ttl_seconds = d.pop("ttl_seconds")
+
+ project_lock_lease_request = cls(
+ ttl_seconds=ttl_seconds,
+ )
+
+ return project_lock_lease_request
+
diff --git a/src/volcano_sdk/_generated/models/project_lock_state.py b/src/volcano_sdk/_generated/models/project_lock_state.py
new file mode 100644
index 00000000..2037d3fd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_lock_state.py
@@ -0,0 +1,90 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectLockState")
+
+
+
+@_attrs_define
+class ProjectLockState:
+ """
+ Attributes:
+ held (bool): Whether the lock is unavailable right now. False means an acquire would
+ succeed. It remains true during the brief grace window after expiry.
+ expires_at (datetime.datetime | Unset): Advisory lease expiry timestamp in UTC. Present only when held.
+ fencing_token (int | Unset): Current holder's fencing token. Present only when held.
+ """
+
+ held: bool
+ expires_at: datetime.datetime | Unset = UNSET
+ fencing_token: int | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ held = self.held
+
+ expires_at: str | Unset = UNSET
+ if not isinstance(self.expires_at, Unset):
+ expires_at = self.expires_at.isoformat()
+
+ fencing_token = self.fencing_token
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "held": held,
+ })
+ if expires_at is not UNSET:
+ field_dict["expires_at"] = expires_at
+ if fencing_token is not UNSET:
+ field_dict["fencing_token"] = fencing_token
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ held = d.pop("held")
+
+ _expires_at = d.pop("expires_at", UNSET)
+ expires_at: datetime.datetime | Unset
+ if isinstance(_expires_at, Unset):
+ expires_at = UNSET
+ else:
+ expires_at = datetime.datetime.fromisoformat(_expires_at)
+
+
+
+
+ fencing_token = d.pop("fencing_token", UNSET)
+
+ project_lock_state = cls(
+ held=held,
+ expires_at=expires_at,
+ fencing_token=fencing_token,
+ )
+
+ return project_lock_state
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_data_status.py b/src/volcano_sdk/_generated/models/project_metrics_data_status.py
new file mode 100644
index 00000000..247ba0b4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_data_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectMetricsDataStatus = Literal['complete', 'no_data', 'partial']
+
+PROJECT_METRICS_DATA_STATUS_VALUES: set[ProjectMetricsDataStatus] = { 'complete', 'no_data', 'partial', }
+
+def check_project_metrics_data_status(value: str) -> ProjectMetricsDataStatus:
+ if value in PROJECT_METRICS_DATA_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_METRICS_DATA_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_metrics_dimensions.py b/src/volcano_sdk/_generated/models/project_metrics_dimensions.py
new file mode 100644
index 00000000..81a8eca1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_dimensions.py
@@ -0,0 +1,83 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_metrics_dimensions_resource_type import check_project_metrics_dimensions_resource_type
+from ..models.project_metrics_dimensions_resource_type import ProjectMetricsDimensionsResourceType
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsDimensions")
+
+
+
+@_attrs_define
+class ProjectMetricsDimensions:
+ """
+ Attributes:
+ region (str | Unset):
+ resource_type (ProjectMetricsDimensionsResourceType | Unset):
+ """
+
+ region: str | Unset = UNSET
+ resource_type: ProjectMetricsDimensionsResourceType | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ region = self.region
+
+ resource_type: str | Unset = UNSET
+ if not isinstance(self.resource_type, Unset):
+ resource_type = self.resource_type
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ })
+ if region is not UNSET:
+ field_dict["region"] = region
+ if resource_type is not UNSET:
+ field_dict["resource_type"] = resource_type
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ region = d.pop("region", UNSET)
+
+ _resource_type = d.pop("resource_type", UNSET)
+ resource_type: ProjectMetricsDimensionsResourceType | Unset
+ if isinstance(_resource_type, Unset):
+ resource_type = UNSET
+ else:
+ resource_type = check_project_metrics_dimensions_resource_type(_resource_type)
+
+
+
+
+ project_metrics_dimensions = cls(
+ region=region,
+ resource_type=resource_type,
+ )
+
+ return project_metrics_dimensions
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_dimensions_resource_type.py b/src/volcano_sdk/_generated/models/project_metrics_dimensions_resource_type.py
new file mode 100644
index 00000000..5c7f0b35
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_dimensions_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectMetricsDimensionsResourceType = Literal['frontend', 'function']
+
+PROJECT_METRICS_DIMENSIONS_RESOURCE_TYPE_VALUES: set[ProjectMetricsDimensionsResourceType] = { 'frontend', 'function', }
+
+def check_project_metrics_dimensions_resource_type(value: str) -> ProjectMetricsDimensionsResourceType:
+ if value in PROJECT_METRICS_DIMENSIONS_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_METRICS_DIMENSIONS_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_metrics_group_by.py b/src/volcano_sdk/_generated/models/project_metrics_group_by.py
new file mode 100644
index 00000000..bb1007c7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_group_by.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectMetricsGroupBy = Literal['region', 'resource_type']
+
+PROJECT_METRICS_GROUP_BY_VALUES: set[ProjectMetricsGroupBy] = { 'region', 'resource_type', }
+
+def check_project_metrics_group_by(value: str) -> ProjectMetricsGroupBy:
+ if value in PROJECT_METRICS_GROUP_BY_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_METRICS_GROUP_BY_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_metrics_metric.py b/src/volcano_sdk/_generated/models/project_metrics_metric.py
new file mode 100644
index 00000000..cde19b81
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_metric.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectMetricsMetric = Literal['availability', 'p95_latency', 'request_count', 'server_error_count']
+
+PROJECT_METRICS_METRIC_VALUES: set[ProjectMetricsMetric] = { 'availability', 'p95_latency', 'request_count', 'server_error_count', }
+
+def check_project_metrics_metric(value: str) -> ProjectMetricsMetric:
+ if value in PROJECT_METRICS_METRIC_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_METRICS_METRIC_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_metrics_query.py b/src/volcano_sdk/_generated/models/project_metrics_query.py
new file mode 100644
index 00000000..d38bffdf
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_query.py
@@ -0,0 +1,95 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_metrics_group_by import check_project_metrics_group_by
+from ..models.project_metrics_group_by import ProjectMetricsGroupBy
+from ..models.project_metrics_metric import check_project_metrics_metric
+from ..models.project_metrics_metric import ProjectMetricsMetric
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsQuery")
+
+
+
+@_attrs_define
+class ProjectMetricsQuery:
+ """
+ Attributes:
+ id (str):
+ metric (ProjectMetricsMetric):
+ group_by (ProjectMetricsGroupBy | Unset):
+ """
+
+ id: str
+ metric: ProjectMetricsMetric
+ group_by: ProjectMetricsGroupBy | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = self.id
+
+ metric: str = self.metric
+
+ group_by: str | Unset = UNSET
+ if not isinstance(self.group_by, Unset):
+ group_by = self.group_by
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "id": id,
+ "metric": metric,
+ })
+ if group_by is not UNSET:
+ field_dict["group_by"] = group_by
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = d.pop("id")
+
+ metric = check_project_metrics_metric(d.pop("metric"))
+
+
+
+
+ _group_by = d.pop("group_by", UNSET)
+ group_by: ProjectMetricsGroupBy | Unset
+ if isinstance(_group_by, Unset):
+ group_by = UNSET
+ else:
+ group_by = check_project_metrics_group_by(_group_by)
+
+
+
+
+ project_metrics_query = cls(
+ id=id,
+ metric=metric,
+ group_by=group_by,
+ )
+
+ return project_metrics_query
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_query_request.py b/src/volcano_sdk/_generated/models/project_metrics_query_request.py
new file mode 100644
index 00000000..8dc3a8dd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_query_request.py
@@ -0,0 +1,90 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_metrics_query import ProjectMetricsQuery
+ from ..models.project_metrics_query_time_range import ProjectMetricsQueryTimeRange
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsQueryRequest")
+
+
+
+@_attrs_define
+class ProjectMetricsQueryRequest:
+ """
+ Attributes:
+ time_range (ProjectMetricsQueryTimeRange):
+ queries (list[ProjectMetricsQuery]):
+ """
+
+ time_range: ProjectMetricsQueryTimeRange
+ queries: list[ProjectMetricsQuery]
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_metrics_query import ProjectMetricsQuery
+ from ..models.project_metrics_query_time_range import ProjectMetricsQueryTimeRange
+ time_range = self.time_range.to_dict()
+
+ queries = []
+ for queries_item_data in self.queries:
+ queries_item = queries_item_data.to_dict()
+ queries.append(queries_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "time_range": time_range,
+ "queries": queries,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_metrics_query import ProjectMetricsQuery
+ from ..models.project_metrics_query_time_range import ProjectMetricsQueryTimeRange
+ d = dict(src_dict)
+ time_range = ProjectMetricsQueryTimeRange.from_dict(d.pop("time_range"))
+
+
+
+
+ queries = []
+ _queries = d.pop("queries")
+ for queries_item_data in (_queries):
+ queries_item = ProjectMetricsQuery.from_dict(queries_item_data)
+
+
+
+ queries.append(queries_item)
+
+
+ project_metrics_query_request = cls(
+ time_range=time_range,
+ queries=queries,
+ )
+
+ return project_metrics_query_request
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_query_response.py b/src/volcano_sdk/_generated/models/project_metrics_query_response.py
new file mode 100644
index 00000000..846e9828
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_query_response.py
@@ -0,0 +1,122 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.project_metrics_result import ProjectMetricsResult
+ from ..models.project_metrics_window import ProjectMetricsWindow
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsQueryResponse")
+
+
+
+@_attrs_define
+class ProjectMetricsQueryResponse:
+ """
+ Attributes:
+ observed_at (datetime.datetime):
+ window (ProjectMetricsWindow):
+ results (list[ProjectMetricsResult]):
+ fresh_through (datetime.datetime | Unset):
+ """
+
+ observed_at: datetime.datetime
+ window: ProjectMetricsWindow
+ results: list[ProjectMetricsResult]
+ fresh_through: datetime.datetime | Unset = UNSET
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_metrics_result import ProjectMetricsResult
+ from ..models.project_metrics_window import ProjectMetricsWindow
+ observed_at = self.observed_at.isoformat()
+
+ window = self.window.to_dict()
+
+ results = []
+ for results_item_data in self.results:
+ results_item = results_item_data.to_dict()
+ results.append(results_item)
+
+
+
+ fresh_through: str | Unset = UNSET
+ if not isinstance(self.fresh_through, Unset):
+ fresh_through = self.fresh_through.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "observed_at": observed_at,
+ "window": window,
+ "results": results,
+ })
+ if fresh_through is not UNSET:
+ field_dict["fresh_through"] = fresh_through
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_metrics_result import ProjectMetricsResult
+ from ..models.project_metrics_window import ProjectMetricsWindow
+ d = dict(src_dict)
+ observed_at = datetime.datetime.fromisoformat(d.pop("observed_at"))
+
+
+
+
+ window = ProjectMetricsWindow.from_dict(d.pop("window"))
+
+
+
+
+ results = []
+ _results = d.pop("results")
+ for results_item_data in (_results):
+ results_item = ProjectMetricsResult.from_dict(results_item_data)
+
+
+
+ results.append(results_item)
+
+
+ _fresh_through = d.pop("fresh_through", UNSET)
+ fresh_through: datetime.datetime | Unset
+ if isinstance(_fresh_through, Unset):
+ fresh_through = UNSET
+ else:
+ fresh_through = datetime.datetime.fromisoformat(_fresh_through)
+
+
+
+
+ project_metrics_query_response = cls(
+ observed_at=observed_at,
+ window=window,
+ results=results,
+ fresh_through=fresh_through,
+ )
+
+ return project_metrics_query_response
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_query_time_range.py b/src/volcano_sdk/_generated/models/project_metrics_query_time_range.py
new file mode 100644
index 00000000..0886fe3b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_query_time_range.py
@@ -0,0 +1,64 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_metrics_query_time_range_window import check_project_metrics_query_time_range_window
+from ..models.project_metrics_query_time_range_window import ProjectMetricsQueryTimeRangeWindow
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsQueryTimeRange")
+
+
+
+@_attrs_define
+class ProjectMetricsQueryTimeRange:
+ """
+ Attributes:
+ window (ProjectMetricsQueryTimeRangeWindow):
+ """
+
+ window: ProjectMetricsQueryTimeRangeWindow
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ window: str = self.window
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "window": window,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ window = check_project_metrics_query_time_range_window(d.pop("window"))
+
+
+
+
+ project_metrics_query_time_range = cls(
+ window=window,
+ )
+
+ return project_metrics_query_time_range
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_query_time_range_window.py b/src/volcano_sdk/_generated/models/project_metrics_query_time_range_window.py
new file mode 100644
index 00000000..91fe4a18
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_query_time_range_window.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectMetricsQueryTimeRangeWindow = Literal['1h', '24h', '30m', '7d']
+
+PROJECT_METRICS_QUERY_TIME_RANGE_WINDOW_VALUES: set[ProjectMetricsQueryTimeRangeWindow] = { '1h', '24h', '30m', '7d', }
+
+def check_project_metrics_query_time_range_window(value: str) -> ProjectMetricsQueryTimeRangeWindow:
+ if value in PROJECT_METRICS_QUERY_TIME_RANGE_WINDOW_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_METRICS_QUERY_TIME_RANGE_WINDOW_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_metrics_result.py b/src/volcano_sdk/_generated/models/project_metrics_result.py
new file mode 100644
index 00000000..0d2c8ef9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_result.py
@@ -0,0 +1,123 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.project_metrics_data_status import check_project_metrics_data_status
+from ..models.project_metrics_data_status import ProjectMetricsDataStatus
+from ..models.project_metrics_metric import check_project_metrics_metric
+from ..models.project_metrics_metric import ProjectMetricsMetric
+from ..models.project_metrics_unit import check_project_metrics_unit
+from ..models.project_metrics_unit import ProjectMetricsUnit
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_metrics_value import ProjectMetricsValue
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsResult")
+
+
+
+@_attrs_define
+class ProjectMetricsResult:
+ """
+ Attributes:
+ id (str):
+ metric (ProjectMetricsMetric):
+ unit (ProjectMetricsUnit):
+ data_status (ProjectMetricsDataStatus):
+ values (list[ProjectMetricsValue]):
+ """
+
+ id: str
+ metric: ProjectMetricsMetric
+ unit: ProjectMetricsUnit
+ data_status: ProjectMetricsDataStatus
+ values: list[ProjectMetricsValue]
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_metrics_value import ProjectMetricsValue
+ id = self.id
+
+ metric: str = self.metric
+
+ unit: str = self.unit
+
+ data_status: str = self.data_status
+
+ values = []
+ for values_item_data in self.values:
+ values_item = values_item_data.to_dict()
+ values.append(values_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "id": id,
+ "metric": metric,
+ "unit": unit,
+ "data_status": data_status,
+ "values": values,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_metrics_value import ProjectMetricsValue
+ d = dict(src_dict)
+ id = d.pop("id")
+
+ metric = check_project_metrics_metric(d.pop("metric"))
+
+
+
+
+ unit = check_project_metrics_unit(d.pop("unit"))
+
+
+
+
+ data_status = check_project_metrics_data_status(d.pop("data_status"))
+
+
+
+
+ values = []
+ _values = d.pop("values")
+ for values_item_data in (_values):
+ values_item = ProjectMetricsValue.from_dict(values_item_data)
+
+
+
+ values.append(values_item)
+
+
+ project_metrics_result = cls(
+ id=id,
+ metric=metric,
+ unit=unit,
+ data_status=data_status,
+ values=values,
+ )
+
+ return project_metrics_result
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_unit.py b/src/volcano_sdk/_generated/models/project_metrics_unit.py
new file mode 100644
index 00000000..8a22a720
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_unit.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectMetricsUnit = Literal['count', 'ratio', 'seconds']
+
+PROJECT_METRICS_UNIT_VALUES: set[ProjectMetricsUnit] = { 'count', 'ratio', 'seconds', }
+
+def check_project_metrics_unit(value: str) -> ProjectMetricsUnit:
+ if value in PROJECT_METRICS_UNIT_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_METRICS_UNIT_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_metrics_value.py b/src/volcano_sdk/_generated/models/project_metrics_value.py
new file mode 100644
index 00000000..39b6cd44
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_value.py
@@ -0,0 +1,74 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.project_metrics_dimensions import ProjectMetricsDimensions
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsValue")
+
+
+
+@_attrs_define
+class ProjectMetricsValue:
+ """
+ Attributes:
+ dimensions (ProjectMetricsDimensions):
+ value (float):
+ """
+
+ dimensions: ProjectMetricsDimensions
+ value: float
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.project_metrics_dimensions import ProjectMetricsDimensions
+ dimensions = self.dimensions.to_dict()
+
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+
+ field_dict.update({
+ "dimensions": dimensions,
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.project_metrics_dimensions import ProjectMetricsDimensions
+ d = dict(src_dict)
+ dimensions = ProjectMetricsDimensions.from_dict(d.pop("dimensions"))
+
+
+
+
+ value = d.pop("value")
+
+ project_metrics_value = cls(
+ dimensions=dimensions,
+ value=value,
+ )
+
+ return project_metrics_value
+
diff --git a/src/volcano_sdk/_generated/models/project_metrics_window.py b/src/volcano_sdk/_generated/models/project_metrics_window.py
new file mode 100644
index 00000000..c9bc1e2e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_metrics_window.py
@@ -0,0 +1,92 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="ProjectMetricsWindow")
+
+
+
+@_attrs_define
+class ProjectMetricsWindow:
+ """
+ Attributes:
+ from_ (datetime.datetime):
+ to (datetime.datetime):
+ """
+
+ from_: datetime.datetime
+ to: datetime.datetime
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from_ = self.from_.isoformat()
+
+ to = self.to.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "from": from_,
+ "to": to,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ from_ = datetime.datetime.fromisoformat(d.pop("from"))
+
+
+
+
+ to = datetime.datetime.fromisoformat(d.pop("to"))
+
+
+
+
+ project_metrics_window = cls(
+ from_=from_,
+ to=to,
+ )
+
+
+ project_metrics_window.additional_properties = d
+ return project_metrics_window
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/project_plan.py b/src/volcano_sdk/_generated/models/project_plan.py
new file mode 100644
index 00000000..031835a6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_plan.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectPlan = Literal['FREE', 'PRO']
+
+PROJECT_PLAN_VALUES: set[ProjectPlan] = { 'FREE', 'PRO', }
+
+def check_project_plan(value: str) -> ProjectPlan:
+ if value in PROJECT_PLAN_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_PLAN_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_status.py b/src/volcano_sdk/_generated/models/project_status.py
new file mode 100644
index 00000000..5fee2cf3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ProjectStatus = Literal['active', 'deleting', 'failed']
+
+PROJECT_STATUS_VALUES: set[ProjectStatus] = { 'active', 'deleting', 'failed', }
+
+def check_project_status(value: str) -> ProjectStatus:
+ if value in PROJECT_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {PROJECT_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/project_usage_response.py b/src/volcano_sdk/_generated/models/project_usage_response.py
new file mode 100644
index 00000000..2a93e454
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/project_usage_response.py
@@ -0,0 +1,145 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+
+if TYPE_CHECKING:
+ from ..models.frontend_usage_data import FrontendUsageData
+ from ..models.metric_usage_data import MetricUsageData
+
+
+
+
+
+T = TypeVar("T", bound="ProjectUsageResponse")
+
+
+
+@_attrs_define
+class ProjectUsageResponse:
+ """ Aggregated usage metrics for a project.
+
+ Attributes:
+ project_id (UUID): Project ID
+ month (str): Usage month in YYYY-MM format Example: 2026-02.
+ metrics (list[MetricUsageData]): Usage metrics for the project
+ frontends (list[FrontendUsageData] | Unset): Per-frontend request totals for the current usage month
+ """
+
+ project_id: UUID
+ month: str
+ metrics: list[MetricUsageData]
+ frontends: list[FrontendUsageData] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.frontend_usage_data import FrontendUsageData
+ from ..models.metric_usage_data import MetricUsageData
+ project_id = str(self.project_id)
+
+ month = self.month
+
+ metrics = []
+ for metrics_item_data in self.metrics:
+ metrics_item = metrics_item_data.to_dict()
+ metrics.append(metrics_item)
+
+
+
+ frontends: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.frontends, Unset):
+ frontends = []
+ for frontends_item_data in self.frontends:
+ frontends_item = frontends_item_data.to_dict()
+ frontends.append(frontends_item)
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "project_id": project_id,
+ "month": month,
+ "metrics": metrics,
+ })
+ if frontends is not UNSET:
+ field_dict["frontends"] = frontends
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.frontend_usage_data import FrontendUsageData
+ from ..models.metric_usage_data import MetricUsageData
+ d = dict(src_dict)
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ month = d.pop("month")
+
+ metrics = []
+ _metrics = d.pop("metrics")
+ for metrics_item_data in (_metrics):
+ metrics_item = MetricUsageData.from_dict(metrics_item_data)
+
+
+
+ metrics.append(metrics_item)
+
+
+ _frontends = d.pop("frontends", UNSET)
+ frontends: list[FrontendUsageData] | Unset = UNSET
+ if _frontends is not UNSET:
+ frontends = []
+ for frontends_item_data in _frontends:
+ frontends_item = FrontendUsageData.from_dict(frontends_item_data)
+
+
+
+ frontends.append(frontends_item)
+
+
+ project_usage_response = cls(
+ project_id=project_id,
+ month=month,
+ metrics=metrics,
+ frontends=frontends,
+ )
+
+
+ project_usage_response.additional_properties = d
+ return project_usage_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/realtime_config.py b/src/volcano_sdk/_generated/models/realtime_config.py
new file mode 100644
index 00000000..f0f38a3a
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/realtime_config.py
@@ -0,0 +1,167 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="RealtimeConfig")
+
+
+
+@_attrs_define
+class RealtimeConfig:
+ """ Realtime configuration for a project.
+ Note: Message size and channels per connection are plan-based (not configurable).
+
+ Attributes:
+ project_id (UUID | Unset): Project ID
+ enabled (bool | Unset): Whether realtime is enabled for this project Default: False.
+ broadcast_enabled (bool | Unset): Whether broadcast channels are enabled Default: True.
+ presence_enabled (bool | Unset): Whether presence tracking is enabled Default: True.
+ postgres_changes_enabled (bool | Unset): Whether Postgres change notifications are enabled Default: True.
+ created_at (datetime.datetime | Unset): When the configuration was created
+ updated_at (datetime.datetime | Unset): When the configuration was last updated
+ """
+
+ project_id: UUID | Unset = UNSET
+ enabled: bool | Unset = False
+ broadcast_enabled: bool | Unset = True
+ presence_enabled: bool | Unset = True
+ postgres_changes_enabled: bool | Unset = True
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ enabled = self.enabled
+
+ broadcast_enabled = self.broadcast_enabled
+
+ presence_enabled = self.presence_enabled
+
+ postgres_changes_enabled = self.postgres_changes_enabled
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if broadcast_enabled is not UNSET:
+ field_dict["broadcast_enabled"] = broadcast_enabled
+ if presence_enabled is not UNSET:
+ field_dict["presence_enabled"] = presence_enabled
+ if postgres_changes_enabled is not UNSET:
+ field_dict["postgres_changes_enabled"] = postgres_changes_enabled
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ enabled = d.pop("enabled", UNSET)
+
+ broadcast_enabled = d.pop("broadcast_enabled", UNSET)
+
+ presence_enabled = d.pop("presence_enabled", UNSET)
+
+ postgres_changes_enabled = d.pop("postgres_changes_enabled", UNSET)
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ realtime_config = cls(
+ project_id=project_id,
+ enabled=enabled,
+ broadcast_enabled=broadcast_enabled,
+ presence_enabled=presence_enabled,
+ postgres_changes_enabled=postgres_changes_enabled,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ realtime_config.additional_properties = d
+ return realtime_config
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/realtime_plan_limits.py b/src/volcano_sdk/_generated/models/realtime_plan_limits.py
new file mode 100644
index 00000000..ef7accdd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/realtime_plan_limits.py
@@ -0,0 +1,115 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="RealtimePlanLimits")
+
+
+
+@_attrs_define
+class RealtimePlanLimits:
+ """ Plan-based limits for realtime features
+
+ Attributes:
+ plan (str | Unset): Plan name (FREE or PRO) Example: FREE.
+ max_connections (int | Unset): Maximum concurrent connections allowed Example: 100.
+ messages_per_month (int | Unset): Maximum messages per month Example: 1000000.
+ message_size_kb (int | Unset): Maximum message size in KB Example: 32.
+ channels_per_conn (int | Unset): Maximum channels per connection Example: 100.
+ """
+
+ plan: str | Unset = UNSET
+ max_connections: int | Unset = UNSET
+ messages_per_month: int | Unset = UNSET
+ message_size_kb: int | Unset = UNSET
+ channels_per_conn: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ plan = self.plan
+
+ max_connections = self.max_connections
+
+ messages_per_month = self.messages_per_month
+
+ message_size_kb = self.message_size_kb
+
+ channels_per_conn = self.channels_per_conn
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if plan is not UNSET:
+ field_dict["plan"] = plan
+ if max_connections is not UNSET:
+ field_dict["max_connections"] = max_connections
+ if messages_per_month is not UNSET:
+ field_dict["messages_per_month"] = messages_per_month
+ if message_size_kb is not UNSET:
+ field_dict["message_size_kb"] = message_size_kb
+ if channels_per_conn is not UNSET:
+ field_dict["channels_per_conn"] = channels_per_conn
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ plan = d.pop("plan", UNSET)
+
+ max_connections = d.pop("max_connections", UNSET)
+
+ messages_per_month = d.pop("messages_per_month", UNSET)
+
+ message_size_kb = d.pop("message_size_kb", UNSET)
+
+ channels_per_conn = d.pop("channels_per_conn", UNSET)
+
+ realtime_plan_limits = cls(
+ plan=plan,
+ max_connections=max_connections,
+ messages_per_month=messages_per_month,
+ message_size_kb=message_size_kb,
+ channels_per_conn=channels_per_conn,
+ )
+
+
+ realtime_plan_limits.additional_properties = d
+ return realtime_plan_limits
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/realtime_stats.py b/src/volcano_sdk/_generated/models/realtime_stats.py
new file mode 100644
index 00000000..8944d34d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/realtime_stats.py
@@ -0,0 +1,132 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.realtime_plan_limits import RealtimePlanLimits
+
+
+
+
+
+T = TypeVar("T", bound="RealtimeStats")
+
+
+
+@_attrs_define
+class RealtimeStats:
+ """ Realtime usage statistics for a project
+
+ Attributes:
+ num_connections (int | Unset): Current number of active connections
+ peak_connections (int | Unset): Peak concurrent connections this usage period
+ last_invoked_at (datetime.datetime | Unset): Most recent realtime activity timestamp across channels
+ limits (RealtimePlanLimits | Unset): Plan-based limits for realtime features
+ """
+
+ num_connections: int | Unset = UNSET
+ peak_connections: int | Unset = UNSET
+ last_invoked_at: datetime.datetime | Unset = UNSET
+ limits: RealtimePlanLimits | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.realtime_plan_limits import RealtimePlanLimits
+ num_connections = self.num_connections
+
+ peak_connections = self.peak_connections
+
+ last_invoked_at: str | Unset = UNSET
+ if not isinstance(self.last_invoked_at, Unset):
+ last_invoked_at = self.last_invoked_at.isoformat()
+
+ limits: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.limits, Unset):
+ limits = self.limits.to_dict()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if num_connections is not UNSET:
+ field_dict["num_connections"] = num_connections
+ if peak_connections is not UNSET:
+ field_dict["peak_connections"] = peak_connections
+ if last_invoked_at is not UNSET:
+ field_dict["last_invoked_at"] = last_invoked_at
+ if limits is not UNSET:
+ field_dict["limits"] = limits
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.realtime_plan_limits import RealtimePlanLimits
+ d = dict(src_dict)
+ num_connections = d.pop("num_connections", UNSET)
+
+ peak_connections = d.pop("peak_connections", UNSET)
+
+ _last_invoked_at = d.pop("last_invoked_at", UNSET)
+ last_invoked_at: datetime.datetime | Unset
+ if isinstance(_last_invoked_at, Unset):
+ last_invoked_at = UNSET
+ else:
+ last_invoked_at = datetime.datetime.fromisoformat(_last_invoked_at)
+
+
+
+
+ _limits = d.pop("limits", UNSET)
+ limits: RealtimePlanLimits | Unset
+ if isinstance(_limits, Unset):
+ limits = UNSET
+ else:
+ limits = RealtimePlanLimits.from_dict(_limits)
+
+
+
+
+ realtime_stats = cls(
+ num_connections=num_connections,
+ peak_connections=peak_connections,
+ last_invoked_at=last_invoked_at,
+ limits=limits,
+ )
+
+
+ realtime_stats.additional_properties = d
+ return realtime_stats
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_provider.py b/src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_provider.py
new file mode 100644
index 00000000..c1c29421
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+RefreshOAuthProviderTokenProvider = Literal['apple', 'github', 'google', 'microsoft']
+
+REFRESH_O_AUTH_PROVIDER_TOKEN_PROVIDER_VALUES: set[RefreshOAuthProviderTokenProvider] = { 'apple', 'github', 'google', 'microsoft', }
+
+def check_refresh_o_auth_provider_token_provider(value: str) -> RefreshOAuthProviderTokenProvider:
+ if value in REFRESH_O_AUTH_PROVIDER_TOKEN_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {REFRESH_O_AUTH_PROVIDER_TOKEN_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_response_200.py b/src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_response_200.py
new file mode 100644
index 00000000..94c7a80b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/refresh_o_auth_provider_token_response_200.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="RefreshOAuthProviderTokenResponse200")
+
+
+
+@_attrs_define
+class RefreshOAuthProviderTokenResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ provider (str | Unset):
+ expires_in (int | Unset):
+ """
+
+ message: str | Unset = UNSET
+ provider: str | Unset = UNSET
+ expires_in: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+ provider = self.provider
+
+ expires_in = self.expires_in
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+ if provider is not UNSET:
+ field_dict["provider"] = provider
+ if expires_in is not UNSET:
+ field_dict["expires_in"] = expires_in
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ provider = d.pop("provider", UNSET)
+
+ expires_in = d.pop("expires_in", UNSET)
+
+ refresh_o_auth_provider_token_response_200 = cls(
+ message=message,
+ provider=provider,
+ expires_in=expires_in,
+ )
+
+
+ refresh_o_auth_provider_token_response_200.additional_properties = d
+ return refresh_o_auth_provider_token_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/render_default_managed_auth_page_action.py b/src/volcano_sdk/_generated/models/render_default_managed_auth_page_action.py
new file mode 100644
index 00000000..07ebff13
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/render_default_managed_auth_page_action.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+RenderDefaultManagedAuthPageAction = Literal['device', 'forgot-password', 'login', 'signup']
+
+RENDER_DEFAULT_MANAGED_AUTH_PAGE_ACTION_VALUES: set[RenderDefaultManagedAuthPageAction] = { 'device', 'forgot-password', 'login', 'signup', }
+
+def check_render_default_managed_auth_page_action(value: str) -> RenderDefaultManagedAuthPageAction:
+ if value in RENDER_DEFAULT_MANAGED_AUTH_PAGE_ACTION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {RENDER_DEFAULT_MANAGED_AUTH_PAGE_ACTION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/reset_database_password_response_200.py b/src/volcano_sdk/_generated/models/reset_database_password_response_200.py
new file mode 100644
index 00000000..03bf2895
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/reset_database_password_response_200.py
@@ -0,0 +1,106 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="ResetDatabasePasswordResponse200")
+
+
+
+@_attrs_define
+class ResetDatabasePasswordResponse200:
+ """
+ Attributes:
+ message (str | Unset):
+ role_name (str | Unset): Volcano-managed per-database client login (also the pgproxy routing username) Example:
+ volcano_client_11111111-1111-1111-1111-111111111111.
+ new_password (str | Unset): New Volcano-managed client password. Always starts with `vpg_`.
+ connection_string (str | Unset): Updated pgproxy connection string using Volcano-managed credentials.
+ """
+
+ message: str | Unset = UNSET
+ role_name: str | Unset = UNSET
+ new_password: str | Unset = UNSET
+ connection_string: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+ role_name = self.role_name
+
+ new_password = self.new_password
+
+ connection_string = self.connection_string
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if message is not UNSET:
+ field_dict["message"] = message
+ if role_name is not UNSET:
+ field_dict["role_name"] = role_name
+ if new_password is not UNSET:
+ field_dict["new_password"] = new_password
+ if connection_string is not UNSET:
+ field_dict["connection_string"] = connection_string
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message", UNSET)
+
+ role_name = d.pop("role_name", UNSET)
+
+ new_password = d.pop("new_password", UNSET)
+
+ connection_string = d.pop("connection_string", UNSET)
+
+ reset_database_password_response_200 = cls(
+ message=message,
+ role_name=role_name,
+ new_password=new_password,
+ connection_string=connection_string,
+ )
+
+
+ reset_database_password_response_200.additional_properties = d
+ return reset_database_password_response_200
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/resolve_function_response.py b/src/volcano_sdk/_generated/models/resolve_function_response.py
new file mode 100644
index 00000000..d29a69ed
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/resolve_function_response.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ResolveFunctionResponse")
+
+
+
+@_attrs_define
+class ResolveFunctionResponse:
+ """
+ Attributes:
+ name (str): DNS-safe function name
+ function_id (UUID): Canonical function ID used for invocation routing
+ cache_ttl_seconds (int): Suggested SDK cache TTL for this name-to-ID mapping
+ """
+
+ name: str
+ function_id: UUID
+ cache_ttl_seconds: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ function_id = str(self.function_id)
+
+ cache_ttl_seconds = self.cache_ttl_seconds
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "name": name,
+ "function_id": function_id,
+ "cache_ttl_seconds": cache_ttl_seconds,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name")
+
+ function_id = UUID(d.pop("function_id"))
+
+
+
+
+ cache_ttl_seconds = d.pop("cache_ttl_seconds")
+
+ resolve_function_response = cls(
+ name=name,
+ function_id=function_id,
+ cache_ttl_seconds=cache_ttl_seconds,
+ )
+
+
+ resolve_function_response.additional_properties = d
+ return resolve_function_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/resource_reference.py b/src/volcano_sdk/_generated/models/resource_reference.py
new file mode 100644
index 00000000..dcdb94a3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/resource_reference.py
@@ -0,0 +1,103 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.resource_reference_type import check_resource_reference_type
+from ..models.resource_reference_type import ResourceReferenceType
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="ResourceReference")
+
+
+
+@_attrs_define
+class ResourceReference:
+ """ Stable reference to a Volcano resource.
+
+ Attributes:
+ type_ (ResourceReferenceType):
+ id (UUID):
+ name (str):
+ """
+
+ type_: ResourceReferenceType
+ id: UUID
+ name: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ type_: str = self.type_
+
+ id = str(self.id)
+
+ name = self.name
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "type": type_,
+ "id": id,
+ "name": name,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ type_ = check_resource_reference_type(d.pop("type"))
+
+
+
+
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ resource_reference = cls(
+ type_=type_,
+ id=id,
+ name=name,
+ )
+
+
+ resource_reference.additional_properties = d
+ return resource_reference
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/resource_reference_type.py b/src/volcano_sdk/_generated/models/resource_reference_type.py
new file mode 100644
index 00000000..17d6629d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/resource_reference_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ResourceReferenceType = Literal['database', 'frontend', 'function', 'project']
+
+RESOURCE_REFERENCE_TYPE_VALUES: set[ResourceReferenceType] = { 'database', 'frontend', 'function', 'project', }
+
+def check_resource_reference_type(value: str) -> ResourceReferenceType:
+ if value in RESOURCE_REFERENCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {RESOURCE_REFERENCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/schedule_request.py b/src/volcano_sdk/_generated/models/schedule_request.py
new file mode 100644
index 00000000..31c60da5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/schedule_request.py
@@ -0,0 +1,101 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.schedule_request_kind import check_schedule_request_kind
+from ..models.schedule_request_kind import ScheduleRequestKind
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="ScheduleRequest")
+
+
+
+@_attrs_define
+class ScheduleRequest:
+ """
+ Attributes:
+ cron_expression (str): Standard 5-field cron expression evaluated in UTC. Seconds fields, descriptors, and
+ Quartz syntax are not supported. Example: */5 * * * *.
+ kind (ScheduleRequestKind | Unset): Default: 'cron'.
+ """
+
+ cron_expression: str
+ kind: ScheduleRequestKind | Unset = 'cron'
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ cron_expression = self.cron_expression
+
+ kind: str | Unset = UNSET
+ if not isinstance(self.kind, Unset):
+ kind = self.kind
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "cron_expression": cron_expression,
+ })
+ if kind is not UNSET:
+ field_dict["kind"] = kind
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ cron_expression = d.pop("cron_expression")
+
+ _kind = d.pop("kind", UNSET)
+ kind: ScheduleRequestKind | Unset
+ if isinstance(_kind, Unset):
+ kind = UNSET
+ else:
+ kind = check_schedule_request_kind(_kind)
+
+
+
+
+ schedule_request = cls(
+ cron_expression=cron_expression,
+ kind=kind,
+ )
+
+
+ schedule_request.additional_properties = d
+ return schedule_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/schedule_request_kind.py b/src/volcano_sdk/_generated/models/schedule_request_kind.py
new file mode 100644
index 00000000..191b3744
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/schedule_request_kind.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+ScheduleRequestKind = Literal['cron']
+
+SCHEDULE_REQUEST_KIND_VALUES: set[ScheduleRequestKind] = { 'cron', }
+
+def check_schedule_request_kind(value: str) -> ScheduleRequestKind:
+ if value in SCHEDULE_REQUEST_KIND_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {SCHEDULE_REQUEST_KIND_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/service_key.py b/src/volcano_sdk/_generated/models/service_key.py
new file mode 100644
index 00000000..f2f25a9f
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/service_key.py
@@ -0,0 +1,183 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="ServiceKey")
+
+
+
+@_attrs_define
+class ServiceKey:
+ """ Service role key for admin operations.
+ **WARNING:** Bypasses all RLS - backend use only!
+
+ Attributes:
+ id (UUID):
+ name (str): Descriptive name for the key
+ key_prefix (str): First 12 characters of the key for display/identification
+ permissions (list[str]): Operations this key may perform. ["*"] grants full admin access
+ (default for keys created without an explicit scope). Scoped keys
+ list specific permissions, e.g. ["functions.invoke", "locks.manage"].
+ Example: ['*'].
+ project_id (UUID | Unset):
+ key_value (str | Unset): Full JWT token for Authorization header.
+ Returned on create, get, and list (decrypted from storage).
+ **Store securely - NEVER expose in frontend code!**
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ name: str
+ key_prefix: str
+ permissions: list[str]
+ project_id: UUID | Unset = UNSET
+ key_value: str | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ name = self.name
+
+ key_prefix = self.key_prefix
+
+ permissions = self.permissions
+
+
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ key_value = self.key_value
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ "key_prefix": key_prefix,
+ "permissions": permissions,
+ })
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if key_value is not UNSET:
+ field_dict["key_value"] = key_value
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ key_prefix = d.pop("key_prefix")
+
+ permissions = cast(list[str], d.pop("permissions"))
+
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ key_value = d.pop("key_value", UNSET)
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ service_key = cls(
+ id=id,
+ name=name,
+ key_prefix=key_prefix,
+ permissions=permissions,
+ project_id=project_id,
+ key_value=key_value,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ service_key.additional_properties = d
+ return service_key
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/set_project_git_production_branch_request.py b/src/volcano_sdk/_generated/models/set_project_git_production_branch_request.py
new file mode 100644
index 00000000..c5e9c766
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/set_project_git_production_branch_request.py
@@ -0,0 +1,77 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="SetProjectGitProductionBranchRequest")
+
+
+
+@_attrs_define
+class SetProjectGitProductionBranchRequest:
+ """
+ Attributes:
+ production_branch (str): The branch a push must land on to deploy. Validated as a Git branch name only — it does
+ not have to exist yet.
+ """
+
+ production_branch: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ production_branch = self.production_branch
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "production_branch": production_branch,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ production_branch = d.pop("production_branch")
+
+ set_project_git_production_branch_request = cls(
+ production_branch=production_branch,
+ )
+
+
+ set_project_git_production_branch_request.additional_properties = d
+ return set_project_git_production_branch_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/start_git_connect_provider.py b/src/volcano_sdk/_generated/models/start_git_connect_provider.py
new file mode 100644
index 00000000..9a1ffa54
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/start_git_connect_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+StartGitConnectProvider = Literal['github']
+
+START_GIT_CONNECT_PROVIDER_VALUES: set[StartGitConnectProvider] = { 'github', }
+
+def check_start_git_connect_provider(value: str) -> StartGitConnectProvider:
+ if value in START_GIT_CONNECT_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {START_GIT_CONNECT_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/storage_bucket.py b/src/volcano_sdk/_generated/models/storage_bucket.py
new file mode 100644
index 00000000..8c9653cc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_bucket.py
@@ -0,0 +1,223 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="StorageBucket")
+
+
+
+@_attrs_define
+class StorageBucket:
+ """ A named container for files within a project.
+ Public access is controlled at the file level via is_public on StorageObject.
+
+ Attributes:
+ id (UUID):
+ name (str): Bucket name (unique within project)
+ project_id (UUID | Unset):
+ file_size_limit (int | None | Unset): Maximum file size in bytes (null for no limit)
+ allowed_mime_types (list[str] | None | Unset): Allowed MIME types (null for all types)
+ last_invoked_at (datetime.datetime | Unset): Most recent bucket operation timestamp
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ name: str
+ project_id: UUID | Unset = UNSET
+ file_size_limit: int | None | Unset = UNSET
+ allowed_mime_types: list[str] | None | Unset = UNSET
+ last_invoked_at: datetime.datetime | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ name = self.name
+
+ project_id: str | Unset = UNSET
+ if not isinstance(self.project_id, Unset):
+ project_id = str(self.project_id)
+
+ file_size_limit: int | None | Unset
+ if isinstance(self.file_size_limit, Unset):
+ file_size_limit = UNSET
+ else:
+ file_size_limit = self.file_size_limit
+
+ allowed_mime_types: list[str] | None | Unset
+ if isinstance(self.allowed_mime_types, Unset):
+ allowed_mime_types = UNSET
+ elif isinstance(self.allowed_mime_types, list):
+ allowed_mime_types = self.allowed_mime_types
+
+
+ else:
+ allowed_mime_types = self.allowed_mime_types
+
+ last_invoked_at: str | Unset = UNSET
+ if not isinstance(self.last_invoked_at, Unset):
+ last_invoked_at = self.last_invoked_at.isoformat()
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "name": name,
+ })
+ if project_id is not UNSET:
+ field_dict["project_id"] = project_id
+ if file_size_limit is not UNSET:
+ field_dict["file_size_limit"] = file_size_limit
+ if allowed_mime_types is not UNSET:
+ field_dict["allowed_mime_types"] = allowed_mime_types
+ if last_invoked_at is not UNSET:
+ field_dict["last_invoked_at"] = last_invoked_at
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ name = d.pop("name")
+
+ _project_id = d.pop("project_id", UNSET)
+ project_id: UUID | Unset
+ if isinstance(_project_id, Unset):
+ project_id = UNSET
+ else:
+ project_id = UUID(_project_id)
+
+
+
+
+ def _parse_file_size_limit(data: object) -> int | None | Unset:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ return cast(int | None | Unset, data)
+
+ file_size_limit = _parse_file_size_limit(d.pop("file_size_limit", UNSET))
+
+
+ def _parse_allowed_mime_types(data: object) -> list[str] | None | Unset:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ try:
+ if not isinstance(data, list):
+ raise TypeError()
+ allowed_mime_types_type_0 = cast(list[str], data)
+
+ return allowed_mime_types_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(list[str] | None | Unset, data)
+
+ allowed_mime_types = _parse_allowed_mime_types(d.pop("allowed_mime_types", UNSET))
+
+
+ _last_invoked_at = d.pop("last_invoked_at", UNSET)
+ last_invoked_at: datetime.datetime | Unset
+ if isinstance(_last_invoked_at, Unset):
+ last_invoked_at = UNSET
+ else:
+ last_invoked_at = datetime.datetime.fromisoformat(_last_invoked_at)
+
+
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ storage_bucket = cls(
+ id=id,
+ name=name,
+ project_id=project_id,
+ file_size_limit=file_size_limit,
+ allowed_mime_types=allowed_mime_types,
+ last_invoked_at=last_invoked_at,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ storage_bucket.additional_properties = d
+ return storage_bucket
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_copy_request.py b/src/volcano_sdk/_generated/models/storage_copy_request.py
new file mode 100644
index 00000000..0bdb768e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_copy_request.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="StorageCopyRequest")
+
+
+
+@_attrs_define
+class StorageCopyRequest:
+ """
+ Attributes:
+ from_ (str): Source path
+ to (str): Destination path
+ """
+
+ from_: str
+ to: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from_ = self.from_
+
+ to = self.to
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "from": from_,
+ "to": to,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ from_ = d.pop("from")
+
+ to = d.pop("to")
+
+ storage_copy_request = cls(
+ from_=from_,
+ to=to,
+ )
+
+
+ storage_copy_request.additional_properties = d
+ return storage_copy_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_list_response.py b/src/volcano_sdk/_generated/models/storage_list_response.py
new file mode 100644
index 00000000..855d44ce
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_list_response.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.storage_object import StorageObject
+
+
+
+
+
+T = TypeVar("T", bound="StorageListResponse")
+
+
+
+@_attrs_define
+class StorageListResponse:
+ """
+ Attributes:
+ objects (list[StorageObject] | Unset):
+ next_cursor (str | Unset): Cursor for next page (empty if no more results)
+ """
+
+ objects: list[StorageObject] | Unset = UNSET
+ next_cursor: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.storage_object import StorageObject
+ objects: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.objects, Unset):
+ objects = []
+ for objects_item_data in self.objects:
+ objects_item = objects_item_data.to_dict()
+ objects.append(objects_item)
+
+
+
+ next_cursor = self.next_cursor
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if objects is not UNSET:
+ field_dict["objects"] = objects
+ if next_cursor is not UNSET:
+ field_dict["next_cursor"] = next_cursor
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.storage_object import StorageObject
+ d = dict(src_dict)
+ _objects = d.pop("objects", UNSET)
+ objects: list[StorageObject] | Unset = UNSET
+ if _objects is not UNSET:
+ objects = []
+ for objects_item_data in _objects:
+ objects_item = StorageObject.from_dict(objects_item_data)
+
+
+
+ objects.append(objects_item)
+
+
+ next_cursor = d.pop("next_cursor", UNSET)
+
+ storage_list_response = cls(
+ objects=objects,
+ next_cursor=next_cursor,
+ )
+
+
+ storage_list_response.additional_properties = d
+ return storage_list_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_move_request.py b/src/volcano_sdk/_generated/models/storage_move_request.py
new file mode 100644
index 00000000..5974bb38
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_move_request.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="StorageMoveRequest")
+
+
+
+@_attrs_define
+class StorageMoveRequest:
+ """
+ Attributes:
+ from_ (str): Source path
+ to (str): Destination path
+ """
+
+ from_: str
+ to: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from_ = self.from_
+
+ to = self.to
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "from": from_,
+ "to": to,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ from_ = d.pop("from")
+
+ to = d.pop("to")
+
+ storage_move_request = cls(
+ from_=from_,
+ to=to,
+ )
+
+
+ storage_move_request.additional_properties = d
+ return storage_move_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_object.py b/src/volcano_sdk/_generated/models/storage_object.py
new file mode 100644
index 00000000..5a7abdcd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_object.py
@@ -0,0 +1,243 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.storage_object_metadata import StorageObjectMetadata
+
+
+
+
+
+T = TypeVar("T", bound="StorageObject")
+
+
+
+@_attrs_define
+class StorageObject:
+ """
+ Attributes:
+ id (UUID):
+ bucket_id (UUID):
+ name (str): Full path within bucket (e.g., "users/abc123/avatar.png")
+ is_public (bool): If true, the file can be downloaded with just an anon key (no user authentication).
+ Files are private by default. Only the owner or a service key can change visibility.
+ Default: False.
+ size (int): File size in bytes
+ mime_type (str): MIME type
+ owner_id (None | Unset | UUID): Auth user who uploaded (null for anonymous/service)
+ etag (str | Unset): Entity tag for cache validation
+ metadata (StorageObjectMetadata | Unset): Custom user metadata (key-value pairs).
+ Limits: Maximum 50 keys, maximum 10KB total serialized size.
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ public_url (str | Unset): Shareable public URL for this file (only set for public files with is_public=true).
+ This URL requires NO authentication and can be embedded in HTML, shared via email, etc.
+ The URL is properly URL-encoded by the server - use it as-is without additional encoding.
+ """
+
+ id: UUID
+ bucket_id: UUID
+ name: str
+ size: int
+ mime_type: str
+ is_public: bool = False
+ owner_id: None | Unset | UUID = UNSET
+ etag: str | Unset = UNSET
+ metadata: StorageObjectMetadata | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ public_url: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.storage_object_metadata import StorageObjectMetadata
+ id = str(self.id)
+
+ bucket_id = str(self.bucket_id)
+
+ name = self.name
+
+ is_public = self.is_public
+
+ size = self.size
+
+ mime_type = self.mime_type
+
+ owner_id: None | str | Unset
+ if isinstance(self.owner_id, Unset):
+ owner_id = UNSET
+ elif isinstance(self.owner_id, UUID):
+ owner_id = str(self.owner_id)
+ else:
+ owner_id = self.owner_id
+
+ etag = self.etag
+
+ metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.metadata, Unset):
+ metadata = self.metadata.to_dict()
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+ public_url = self.public_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "bucket_id": bucket_id,
+ "name": name,
+ "is_public": is_public,
+ "size": size,
+ "mime_type": mime_type,
+ })
+ if owner_id is not UNSET:
+ field_dict["owner_id"] = owner_id
+ if etag is not UNSET:
+ field_dict["etag"] = etag
+ if metadata is not UNSET:
+ field_dict["metadata"] = metadata
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+ if public_url is not UNSET:
+ field_dict["public_url"] = public_url
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.storage_object_metadata import StorageObjectMetadata
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ bucket_id = UUID(d.pop("bucket_id"))
+
+
+
+
+ name = d.pop("name")
+
+ is_public = d.pop("is_public")
+
+ size = d.pop("size")
+
+ mime_type = d.pop("mime_type")
+
+ def _parse_owner_id(data: object) -> None | Unset | UUID:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ try:
+ if not isinstance(data, str):
+ raise TypeError()
+ owner_id_type_0 = UUID(data)
+
+
+
+ return owner_id_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(None | Unset | UUID, data)
+
+ owner_id = _parse_owner_id(d.pop("owner_id", UNSET))
+
+
+ etag = d.pop("etag", UNSET)
+
+ _metadata = d.pop("metadata", UNSET)
+ metadata: StorageObjectMetadata | Unset
+ if isinstance(_metadata, Unset):
+ metadata = UNSET
+ else:
+ metadata = StorageObjectMetadata.from_dict(_metadata)
+
+
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ public_url = d.pop("public_url", UNSET)
+
+ storage_object = cls(
+ id=id,
+ bucket_id=bucket_id,
+ name=name,
+ is_public=is_public,
+ size=size,
+ mime_type=mime_type,
+ owner_id=owner_id,
+ etag=etag,
+ metadata=metadata,
+ created_at=created_at,
+ updated_at=updated_at,
+ public_url=public_url,
+ )
+
+
+ storage_object.additional_properties = d
+ return storage_object
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_object_metadata.py b/src/volcano_sdk/_generated/models/storage_object_metadata.py
new file mode 100644
index 00000000..e7ebf651
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_object_metadata.py
@@ -0,0 +1,67 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="StorageObjectMetadata")
+
+
+
+@_attrs_define
+class StorageObjectMetadata:
+ """ Custom user metadata (key-value pairs).
+ Limits: Maximum 50 keys, maximum 10KB total serialized size.
+
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ storage_object_metadata = cls(
+ )
+
+
+ storage_object_metadata.additional_properties = d
+ return storage_object_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_object_with_bucket.py b/src/volcano_sdk/_generated/models/storage_object_with_bucket.py
new file mode 100644
index 00000000..bcda8fa9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_object_with_bucket.py
@@ -0,0 +1,248 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.storage_object_with_bucket_metadata import StorageObjectWithBucketMetadata
+
+
+
+
+
+T = TypeVar("T", bound="StorageObjectWithBucket")
+
+
+
+@_attrs_define
+class StorageObjectWithBucket:
+ """ Storage object with bucket name included (for admin listing across buckets)
+
+ Attributes:
+ id (UUID):
+ bucket_id (UUID):
+ bucket_name (str): Name of the bucket containing this object
+ name (str): Full path within bucket
+ is_public (bool): Default: False.
+ size (int): File size in bytes
+ mime_type (str):
+ owner_id (None | Unset | UUID): Auth user who uploaded (null for anonymous/service)
+ etag (str | Unset):
+ metadata (StorageObjectWithBucketMetadata | Unset):
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ public_url (str | Unset): Shareable public URL for this file (only set for public files with is_public=true).
+ This URL requires NO authentication and can be embedded in HTML, shared via email, etc.
+ """
+
+ id: UUID
+ bucket_id: UUID
+ bucket_name: str
+ name: str
+ size: int
+ mime_type: str
+ is_public: bool = False
+ owner_id: None | Unset | UUID = UNSET
+ etag: str | Unset = UNSET
+ metadata: StorageObjectWithBucketMetadata | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ public_url: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.storage_object_with_bucket_metadata import StorageObjectWithBucketMetadata
+ id = str(self.id)
+
+ bucket_id = str(self.bucket_id)
+
+ bucket_name = self.bucket_name
+
+ name = self.name
+
+ is_public = self.is_public
+
+ size = self.size
+
+ mime_type = self.mime_type
+
+ owner_id: None | str | Unset
+ if isinstance(self.owner_id, Unset):
+ owner_id = UNSET
+ elif isinstance(self.owner_id, UUID):
+ owner_id = str(self.owner_id)
+ else:
+ owner_id = self.owner_id
+
+ etag = self.etag
+
+ metadata: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.metadata, Unset):
+ metadata = self.metadata.to_dict()
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+ public_url = self.public_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "bucket_id": bucket_id,
+ "bucket_name": bucket_name,
+ "name": name,
+ "is_public": is_public,
+ "size": size,
+ "mime_type": mime_type,
+ })
+ if owner_id is not UNSET:
+ field_dict["owner_id"] = owner_id
+ if etag is not UNSET:
+ field_dict["etag"] = etag
+ if metadata is not UNSET:
+ field_dict["metadata"] = metadata
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+ if public_url is not UNSET:
+ field_dict["public_url"] = public_url
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.storage_object_with_bucket_metadata import StorageObjectWithBucketMetadata
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ bucket_id = UUID(d.pop("bucket_id"))
+
+
+
+
+ bucket_name = d.pop("bucket_name")
+
+ name = d.pop("name")
+
+ is_public = d.pop("is_public")
+
+ size = d.pop("size")
+
+ mime_type = d.pop("mime_type")
+
+ def _parse_owner_id(data: object) -> None | Unset | UUID:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ try:
+ if not isinstance(data, str):
+ raise TypeError()
+ owner_id_type_0 = UUID(data)
+
+
+
+ return owner_id_type_0
+ except (TypeError, ValueError, AttributeError, KeyError):
+ pass
+ return cast(None | Unset | UUID, data)
+
+ owner_id = _parse_owner_id(d.pop("owner_id", UNSET))
+
+
+ etag = d.pop("etag", UNSET)
+
+ _metadata = d.pop("metadata", UNSET)
+ metadata: StorageObjectWithBucketMetadata | Unset
+ if isinstance(_metadata, Unset):
+ metadata = UNSET
+ else:
+ metadata = StorageObjectWithBucketMetadata.from_dict(_metadata)
+
+
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ public_url = d.pop("public_url", UNSET)
+
+ storage_object_with_bucket = cls(
+ id=id,
+ bucket_id=bucket_id,
+ bucket_name=bucket_name,
+ name=name,
+ is_public=is_public,
+ size=size,
+ mime_type=mime_type,
+ owner_id=owner_id,
+ etag=etag,
+ metadata=metadata,
+ created_at=created_at,
+ updated_at=updated_at,
+ public_url=public_url,
+ )
+
+
+ storage_object_with_bucket.additional_properties = d
+ return storage_object_with_bucket
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_object_with_bucket_metadata.py b/src/volcano_sdk/_generated/models/storage_object_with_bucket_metadata.py
new file mode 100644
index 00000000..2fb767dd
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_object_with_bucket_metadata.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="StorageObjectWithBucketMetadata")
+
+
+
+@_attrs_define
+class StorageObjectWithBucketMetadata:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ storage_object_with_bucket_metadata = cls(
+ )
+
+
+ storage_object_with_bucket_metadata.additional_properties = d
+ return storage_object_with_bucket_metadata
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_policy.py b/src/volcano_sdk/_generated/models/storage_policy.py
new file mode 100644
index 00000000..a05087b0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_policy.py
@@ -0,0 +1,166 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.storage_policy_operation import check_storage_policy_operation
+from ..models.storage_policy_operation import StoragePolicyOperation
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="StoragePolicy")
+
+
+
+@_attrs_define
+class StoragePolicy:
+ """
+ Attributes:
+ id (UUID):
+ bucket_id (UUID):
+ name (str): Policy name (unique within bucket)
+ operation (StoragePolicyOperation): Operation this policy applies to
+ definition (str): Policy expression evaluated at request time.
+ Examples:
+ - "true" - Allow all
+ - "auth.uid() = owner_id" - Owner only
+ - "auth.role() = 'authenticated'" - Authenticated users
+ - "(storage.foldername(name))[1] = auth.uid()::text" - User's folder
+ created_at (datetime.datetime | Unset):
+ updated_at (datetime.datetime | Unset):
+ """
+
+ id: UUID
+ bucket_id: UUID
+ name: str
+ operation: StoragePolicyOperation
+ definition: str
+ created_at: datetime.datetime | Unset = UNSET
+ updated_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ bucket_id = str(self.bucket_id)
+
+ name = self.name
+
+ operation: str = self.operation
+
+ definition = self.definition
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+ updated_at: str | Unset = UNSET
+ if not isinstance(self.updated_at, Unset):
+ updated_at = self.updated_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "bucket_id": bucket_id,
+ "name": name,
+ "operation": operation,
+ "definition": definition,
+ })
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+ if updated_at is not UNSET:
+ field_dict["updated_at"] = updated_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ bucket_id = UUID(d.pop("bucket_id"))
+
+
+
+
+ name = d.pop("name")
+
+ operation = check_storage_policy_operation(d.pop("operation"))
+
+
+
+
+ definition = d.pop("definition")
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ _updated_at = d.pop("updated_at", UNSET)
+ updated_at: datetime.datetime | Unset
+ if isinstance(_updated_at, Unset):
+ updated_at = UNSET
+ else:
+ updated_at = datetime.datetime.fromisoformat(_updated_at)
+
+
+
+
+ storage_policy = cls(
+ id=id,
+ bucket_id=bucket_id,
+ name=name,
+ operation=operation,
+ definition=definition,
+ created_at=created_at,
+ updated_at=updated_at,
+ )
+
+
+ storage_policy.additional_properties = d
+ return storage_policy
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_policy_operation.py b/src/volcano_sdk/_generated/models/storage_policy_operation.py
new file mode 100644
index 00000000..fb81909c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_policy_operation.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+StoragePolicyOperation = Literal['DELETE', 'INSERT', 'SELECT', 'UPDATE']
+
+STORAGE_POLICY_OPERATION_VALUES: set[StoragePolicyOperation] = { 'DELETE', 'INSERT', 'SELECT', 'UPDATE', }
+
+def check_storage_policy_operation(value: str) -> StoragePolicyOperation:
+ if value in STORAGE_POLICY_OPERATION_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {STORAGE_POLICY_OPERATION_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/storage_stats.py b/src/volcano_sdk/_generated/models/storage_stats.py
new file mode 100644
index 00000000..4a3cfae1
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_stats.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="StorageStats")
+
+
+
+@_attrs_define
+class StorageStats:
+ """ Aggregate storage statistics for a project
+
+ Attributes:
+ bucket_count (int): Number of storage buckets
+ object_count (int): Total number of stored files
+ total_size (int): Total storage used in bytes
+ """
+
+ bucket_count: int
+ object_count: int
+ total_size: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ bucket_count = self.bucket_count
+
+ object_count = self.object_count
+
+ total_size = self.total_size
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "bucket_count": bucket_count,
+ "object_count": object_count,
+ "total_size": total_size,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ bucket_count = d.pop("bucket_count")
+
+ object_count = d.pop("object_count")
+
+ total_size = d.pop("total_size")
+
+ storage_stats = cls(
+ bucket_count=bucket_count,
+ object_count=object_count,
+ total_size=total_size,
+ )
+
+
+ storage_stats.additional_properties = d
+ return storage_stats
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/storage_visibility_request.py b/src/volcano_sdk/_generated/models/storage_visibility_request.py
new file mode 100644
index 00000000..9223f091
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/storage_visibility_request.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="StorageVisibilityRequest")
+
+
+
+@_attrs_define
+class StorageVisibilityRequest:
+ """
+ Attributes:
+ is_public (bool): Whether the file should be publicly accessible
+ """
+
+ is_public: bool
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ is_public = self.is_public
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "is_public": is_public,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ is_public = d.pop("is_public")
+
+ storage_visibility_request = cls(
+ is_public=is_public,
+ )
+
+
+ storage_visibility_request.additional_properties = d
+ return storage_visibility_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/summarize_project_deployments_resource_type.py b/src/volcano_sdk/_generated/models/summarize_project_deployments_resource_type.py
new file mode 100644
index 00000000..c1173c95
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/summarize_project_deployments_resource_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+SummarizeProjectDeploymentsResourceType = Literal['frontend', 'function']
+
+SUMMARIZE_PROJECT_DEPLOYMENTS_RESOURCE_TYPE_VALUES: set[SummarizeProjectDeploymentsResourceType] = { 'frontend', 'function', }
+
+def check_summarize_project_deployments_resource_type(value: str) -> SummarizeProjectDeploymentsResourceType:
+ if value in SUMMARIZE_PROJECT_DEPLOYMENTS_RESOURCE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {SUMMARIZE_PROJECT_DEPLOYMENTS_RESOURCE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/test_email_request.py b/src/volcano_sdk/_generated/models/test_email_request.py
new file mode 100644
index 00000000..18adfc61
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/test_email_request.py
@@ -0,0 +1,115 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="TestEmailRequest")
+
+
+
+@_attrs_define
+class TestEmailRequest:
+ """ When `html_body` or `text_body` is provided the backend renders
+ those (plus optional `subject`) through html/text templates
+ against the standard `Data` (ProjectName, Name, SiteURL)
+ and sends the result — used by the template-editor "Send Test"
+ affordance to preview an unsaved template. When both bodies are
+ omitted a hardcoded diagnostic message is sent to verify SMTP
+ credentials and `subject` is ignored. Sending `subject` alone
+ (without a body) is rejected with 400.
+
+ Attributes:
+ to_email (str): Recipient address for the diagnostic email.
+ subject (str | Unset): Optional subject override, rendered as a text/template. Only
+ applied on the override path — requires `html_body` or
+ `text_body` to also be set, otherwise the request is
+ rejected with 400.
+ html_body (str | Unset): Optional HTML body override. Rendered as an html/template. Max 256 KiB.
+ text_body (str | Unset): Optional plain-text body override. Rendered as a text/template. Max 256 KiB.
+ """
+
+ to_email: str
+ subject: str | Unset = UNSET
+ html_body: str | Unset = UNSET
+ text_body: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ to_email = self.to_email
+
+ subject = self.subject
+
+ html_body = self.html_body
+
+ text_body = self.text_body
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "to_email": to_email,
+ })
+ if subject is not UNSET:
+ field_dict["subject"] = subject
+ if html_body is not UNSET:
+ field_dict["html_body"] = html_body
+ if text_body is not UNSET:
+ field_dict["text_body"] = text_body
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ to_email = d.pop("to_email")
+
+ subject = d.pop("subject", UNSET)
+
+ html_body = d.pop("html_body", UNSET)
+
+ text_body = d.pop("text_body", UNSET)
+
+ test_email_request = cls(
+ to_email=to_email,
+ subject=subject,
+ html_body=html_body,
+ text_body=text_body,
+ )
+
+
+ test_email_request.additional_properties = d
+ return test_email_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/test_email_response.py b/src/volcano_sdk/_generated/models/test_email_response.py
new file mode 100644
index 00000000..3ae1faad
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/test_email_response.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="TestEmailResponse")
+
+
+
+@_attrs_define
+class TestEmailResponse:
+ """
+ Attributes:
+ success (bool):
+ """
+
+ success: bool
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ success = self.success
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "success": success,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ success = d.pop("success")
+
+ test_email_response = cls(
+ success=success,
+ )
+
+
+ test_email_response.additional_properties = d
+ return test_email_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/unban_user_response.py b/src/volcano_sdk/_generated/models/unban_user_response.py
new file mode 100644
index 00000000..28053696
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/unban_user_response.py
@@ -0,0 +1,111 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.unban_user_response_status import check_unban_user_response_status
+from ..models.unban_user_response_status import UnbanUserResponseStatus
+from typing import cast
+from uuid import UUID
+
+
+
+
+
+
+T = TypeVar("T", bound="UnbanUserResponse")
+
+
+
+@_attrs_define
+class UnbanUserResponse:
+ """ Response when unbanning a user
+
+ Attributes:
+ message (str): Example: User unbanned successfully.
+ user_id (UUID):
+ email (str):
+ status (UnbanUserResponseStatus):
+ """
+
+ message: str
+ user_id: UUID
+ email: str
+ status: UnbanUserResponseStatus
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ message = self.message
+
+ user_id = str(self.user_id)
+
+ email = self.email
+
+ status: str = self.status
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "message": message,
+ "user_id": user_id,
+ "email": email,
+ "status": status,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ message = d.pop("message")
+
+ user_id = UUID(d.pop("user_id"))
+
+
+
+
+ email = d.pop("email")
+
+ status = check_unban_user_response_status(d.pop("status"))
+
+
+
+
+ unban_user_response = cls(
+ message=message,
+ user_id=user_id,
+ email=email,
+ status=status,
+ )
+
+
+ unban_user_response.additional_properties = d
+ return unban_user_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/unban_user_response_status.py b/src/volcano_sdk/_generated/models/unban_user_response_status.py
new file mode 100644
index 00000000..0a5eab82
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/unban_user_response_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+UnbanUserResponseStatus = Literal['active']
+
+UNBAN_USER_RESPONSE_STATUS_VALUES: set[UnbanUserResponseStatus] = { 'active', }
+
+def check_unban_user_response_status(value: str) -> UnbanUserResponseStatus:
+ if value in UNBAN_USER_RESPONSE_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {UNBAN_USER_RESPONSE_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/update_auth_config_request.py b/src/volcano_sdk/_generated/models/update_auth_config_request.py
new file mode 100644
index 00000000..d0f94148
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_auth_config_request.py
@@ -0,0 +1,485 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.update_auth_config_request_allowed_email_domains_mode import check_update_auth_config_request_allowed_email_domains_mode
+from ..models.update_auth_config_request_allowed_email_domains_mode import UpdateAuthConfigRequestAllowedEmailDomainsMode
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateAuthConfigRequest")
+
+
+
+@_attrs_define
+class UpdateAuthConfigRequest:
+ """ All fields optional - only include fields you want to update. Validation rule: require_email_confirmation=true
+ requires email_enabled=true.
+
+ Attributes:
+ access_token_lifetime (int | Unset):
+ refresh_token_lifetime (int | Unset):
+ inactivity_timeout (int | Unset):
+ max_session_duration (int | Unset):
+ min_password_length (int | Unset):
+ require_uppercase (bool | Unset):
+ require_lowercase (bool | Unset):
+ require_numbers (bool | Unset):
+ require_special_chars (bool | Unset):
+ enable_signup (bool | Unset): Master switch for signups across ALL providers
+ enable_email_password (bool | Unset): Enable/disable email/password provider
+ rate_limit_signup (int | Unset):
+ rate_limit_signin (int | Unset):
+ rate_limit_token_refresh (int | Unset):
+ cors_allow_credentials (bool | Unset):
+ cors_max_age (int | Unset):
+ enable_anonymous_signins (bool | Unset):
+ allowed_email_domains (list[str] | Unset): Replaces the email domain allowlist. Empty array removes the
+ restriction so any domain can sign up. Entries must be bare domains
+ such as `domain1.com` and are stored normalized (lowercase, no `@`
+ prefix); matching is exact, so subdomains need their own entry. At
+ most 100 entries.
+
+ Restricting signups is a PRO feature to configure and to enforce: a
+ FREE project can only remove the restriction and gets 403 for any
+ other change, and the list it keeps is parked until it upgrades.
+ Example: ['domain1.com', 'domain2.com'].
+ allowed_email_domains_mode (UpdateAuthConfigRequestAllowedEmailDomainsMode | Unset): How far
+ `allowed_email_domains` reaches. `signup` gates account
+ creation only. `signup_and_signin` also blocks sign-in for accounts
+ outside the list; switching to it, or narrowing the list while in
+ it, deletes the sessions of every account it locks out. `disabled`
+ keeps the list without enforcing it.
+ allow_password_reset (bool | Unset):
+ password_reset_timeout (int | Unset):
+ max_password_history (int | Unset):
+ require_email_confirmation (bool | Unset): Require users to confirm email before sign-in. Can only be true when
+ email_enabled is true.
+ email_confirmation_timeout (int | Unset): Email confirmation token expiry in seconds.
+ auto_link_verified_oauth (bool | Unset): Link a verified OAuth identity to an existing confirmed account with
+ the same email instead of returning a conflict. Requires require_email_confirmation to be true.
+ email_enabled (bool | Unset): Enable transactional email sending. Cannot be false while
+ require_email_confirmation is true.
+ email_from_address (str | Unset):
+ email_from_name (str | Unset):
+ smtp_host (str | Unset):
+ smtp_port (int | Unset):
+ smtp_username (str | Unset):
+ smtp_password (str | Unset): Replacement SMTP password. Omit this field to preserve the configured password. The
+ value is encrypted at rest and never returned.
+ smtp_use_tls (bool | Unset):
+ email_confirmation_subject (str | Unset):
+ email_password_reset_subject (str | Unset):
+ email_password_changed_subject (str | Unset):
+ managed_auth_enabled (bool | Unset): Enable or disable managed auth hosted pages for the project.
+ post_auth_redirect_url (str | Unset): Must be included in allowed_redirect_urls when set.
+ allowed_redirect_urls (list[str] | Unset): Redirect allowlist. Every entry must be a valid http/https URL.
+ post_logout_redirect_url (str | Unset): Must be included in allowed_redirect_urls when set.
+ device_verification_url (str | Unset): Optional custom device-authorization verification page. Must be a
+ valid http/https URL (not tied to allowed_redirect_urls). When set,
+ device-code logins return this URL (with user_code) instead of the
+ managed device page. Send an empty string to clear the override.
+ """
+
+ access_token_lifetime: int | Unset = UNSET
+ refresh_token_lifetime: int | Unset = UNSET
+ inactivity_timeout: int | Unset = UNSET
+ max_session_duration: int | Unset = UNSET
+ min_password_length: int | Unset = UNSET
+ require_uppercase: bool | Unset = UNSET
+ require_lowercase: bool | Unset = UNSET
+ require_numbers: bool | Unset = UNSET
+ require_special_chars: bool | Unset = UNSET
+ enable_signup: bool | Unset = UNSET
+ enable_email_password: bool | Unset = UNSET
+ rate_limit_signup: int | Unset = UNSET
+ rate_limit_signin: int | Unset = UNSET
+ rate_limit_token_refresh: int | Unset = UNSET
+ cors_allow_credentials: bool | Unset = UNSET
+ cors_max_age: int | Unset = UNSET
+ enable_anonymous_signins: bool | Unset = UNSET
+ allowed_email_domains: list[str] | Unset = UNSET
+ allowed_email_domains_mode: UpdateAuthConfigRequestAllowedEmailDomainsMode | Unset = UNSET
+ allow_password_reset: bool | Unset = UNSET
+ password_reset_timeout: int | Unset = UNSET
+ max_password_history: int | Unset = UNSET
+ require_email_confirmation: bool | Unset = UNSET
+ email_confirmation_timeout: int | Unset = UNSET
+ auto_link_verified_oauth: bool | Unset = UNSET
+ email_enabled: bool | Unset = UNSET
+ email_from_address: str | Unset = UNSET
+ email_from_name: str | Unset = UNSET
+ smtp_host: str | Unset = UNSET
+ smtp_port: int | Unset = UNSET
+ smtp_username: str | Unset = UNSET
+ smtp_password: str | Unset = UNSET
+ smtp_use_tls: bool | Unset = UNSET
+ email_confirmation_subject: str | Unset = UNSET
+ email_password_reset_subject: str | Unset = UNSET
+ email_password_changed_subject: str | Unset = UNSET
+ managed_auth_enabled: bool | Unset = UNSET
+ post_auth_redirect_url: str | Unset = UNSET
+ allowed_redirect_urls: list[str] | Unset = UNSET
+ post_logout_redirect_url: str | Unset = UNSET
+ device_verification_url: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ access_token_lifetime = self.access_token_lifetime
+
+ refresh_token_lifetime = self.refresh_token_lifetime
+
+ inactivity_timeout = self.inactivity_timeout
+
+ max_session_duration = self.max_session_duration
+
+ min_password_length = self.min_password_length
+
+ require_uppercase = self.require_uppercase
+
+ require_lowercase = self.require_lowercase
+
+ require_numbers = self.require_numbers
+
+ require_special_chars = self.require_special_chars
+
+ enable_signup = self.enable_signup
+
+ enable_email_password = self.enable_email_password
+
+ rate_limit_signup = self.rate_limit_signup
+
+ rate_limit_signin = self.rate_limit_signin
+
+ rate_limit_token_refresh = self.rate_limit_token_refresh
+
+ cors_allow_credentials = self.cors_allow_credentials
+
+ cors_max_age = self.cors_max_age
+
+ enable_anonymous_signins = self.enable_anonymous_signins
+
+ allowed_email_domains: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_email_domains, Unset):
+ allowed_email_domains = self.allowed_email_domains
+
+
+
+ allowed_email_domains_mode: str | Unset = UNSET
+ if not isinstance(self.allowed_email_domains_mode, Unset):
+ allowed_email_domains_mode = self.allowed_email_domains_mode
+
+
+ allow_password_reset = self.allow_password_reset
+
+ password_reset_timeout = self.password_reset_timeout
+
+ max_password_history = self.max_password_history
+
+ require_email_confirmation = self.require_email_confirmation
+
+ email_confirmation_timeout = self.email_confirmation_timeout
+
+ auto_link_verified_oauth = self.auto_link_verified_oauth
+
+ email_enabled = self.email_enabled
+
+ email_from_address = self.email_from_address
+
+ email_from_name = self.email_from_name
+
+ smtp_host = self.smtp_host
+
+ smtp_port = self.smtp_port
+
+ smtp_username = self.smtp_username
+
+ smtp_password = self.smtp_password
+
+ smtp_use_tls = self.smtp_use_tls
+
+ email_confirmation_subject = self.email_confirmation_subject
+
+ email_password_reset_subject = self.email_password_reset_subject
+
+ email_password_changed_subject = self.email_password_changed_subject
+
+ managed_auth_enabled = self.managed_auth_enabled
+
+ post_auth_redirect_url = self.post_auth_redirect_url
+
+ allowed_redirect_urls: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_redirect_urls, Unset):
+ allowed_redirect_urls = self.allowed_redirect_urls
+
+
+
+ post_logout_redirect_url = self.post_logout_redirect_url
+
+ device_verification_url = self.device_verification_url
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if access_token_lifetime is not UNSET:
+ field_dict["access_token_lifetime"] = access_token_lifetime
+ if refresh_token_lifetime is not UNSET:
+ field_dict["refresh_token_lifetime"] = refresh_token_lifetime
+ if inactivity_timeout is not UNSET:
+ field_dict["inactivity_timeout"] = inactivity_timeout
+ if max_session_duration is not UNSET:
+ field_dict["max_session_duration"] = max_session_duration
+ if min_password_length is not UNSET:
+ field_dict["min_password_length"] = min_password_length
+ if require_uppercase is not UNSET:
+ field_dict["require_uppercase"] = require_uppercase
+ if require_lowercase is not UNSET:
+ field_dict["require_lowercase"] = require_lowercase
+ if require_numbers is not UNSET:
+ field_dict["require_numbers"] = require_numbers
+ if require_special_chars is not UNSET:
+ field_dict["require_special_chars"] = require_special_chars
+ if enable_signup is not UNSET:
+ field_dict["enable_signup"] = enable_signup
+ if enable_email_password is not UNSET:
+ field_dict["enable_email_password"] = enable_email_password
+ if rate_limit_signup is not UNSET:
+ field_dict["rate_limit_signup"] = rate_limit_signup
+ if rate_limit_signin is not UNSET:
+ field_dict["rate_limit_signin"] = rate_limit_signin
+ if rate_limit_token_refresh is not UNSET:
+ field_dict["rate_limit_token_refresh"] = rate_limit_token_refresh
+ if cors_allow_credentials is not UNSET:
+ field_dict["cors_allow_credentials"] = cors_allow_credentials
+ if cors_max_age is not UNSET:
+ field_dict["cors_max_age"] = cors_max_age
+ if enable_anonymous_signins is not UNSET:
+ field_dict["enable_anonymous_signins"] = enable_anonymous_signins
+ if allowed_email_domains is not UNSET:
+ field_dict["allowed_email_domains"] = allowed_email_domains
+ if allowed_email_domains_mode is not UNSET:
+ field_dict["allowed_email_domains_mode"] = allowed_email_domains_mode
+ if allow_password_reset is not UNSET:
+ field_dict["allow_password_reset"] = allow_password_reset
+ if password_reset_timeout is not UNSET:
+ field_dict["password_reset_timeout"] = password_reset_timeout
+ if max_password_history is not UNSET:
+ field_dict["max_password_history"] = max_password_history
+ if require_email_confirmation is not UNSET:
+ field_dict["require_email_confirmation"] = require_email_confirmation
+ if email_confirmation_timeout is not UNSET:
+ field_dict["email_confirmation_timeout"] = email_confirmation_timeout
+ if auto_link_verified_oauth is not UNSET:
+ field_dict["auto_link_verified_oauth"] = auto_link_verified_oauth
+ if email_enabled is not UNSET:
+ field_dict["email_enabled"] = email_enabled
+ if email_from_address is not UNSET:
+ field_dict["email_from_address"] = email_from_address
+ if email_from_name is not UNSET:
+ field_dict["email_from_name"] = email_from_name
+ if smtp_host is not UNSET:
+ field_dict["smtp_host"] = smtp_host
+ if smtp_port is not UNSET:
+ field_dict["smtp_port"] = smtp_port
+ if smtp_username is not UNSET:
+ field_dict["smtp_username"] = smtp_username
+ if smtp_password is not UNSET:
+ field_dict["smtp_password"] = smtp_password
+ if smtp_use_tls is not UNSET:
+ field_dict["smtp_use_tls"] = smtp_use_tls
+ if email_confirmation_subject is not UNSET:
+ field_dict["email_confirmation_subject"] = email_confirmation_subject
+ if email_password_reset_subject is not UNSET:
+ field_dict["email_password_reset_subject"] = email_password_reset_subject
+ if email_password_changed_subject is not UNSET:
+ field_dict["email_password_changed_subject"] = email_password_changed_subject
+ if managed_auth_enabled is not UNSET:
+ field_dict["managed_auth_enabled"] = managed_auth_enabled
+ if post_auth_redirect_url is not UNSET:
+ field_dict["post_auth_redirect_url"] = post_auth_redirect_url
+ if allowed_redirect_urls is not UNSET:
+ field_dict["allowed_redirect_urls"] = allowed_redirect_urls
+ if post_logout_redirect_url is not UNSET:
+ field_dict["post_logout_redirect_url"] = post_logout_redirect_url
+ if device_verification_url is not UNSET:
+ field_dict["device_verification_url"] = device_verification_url
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ access_token_lifetime = d.pop("access_token_lifetime", UNSET)
+
+ refresh_token_lifetime = d.pop("refresh_token_lifetime", UNSET)
+
+ inactivity_timeout = d.pop("inactivity_timeout", UNSET)
+
+ max_session_duration = d.pop("max_session_duration", UNSET)
+
+ min_password_length = d.pop("min_password_length", UNSET)
+
+ require_uppercase = d.pop("require_uppercase", UNSET)
+
+ require_lowercase = d.pop("require_lowercase", UNSET)
+
+ require_numbers = d.pop("require_numbers", UNSET)
+
+ require_special_chars = d.pop("require_special_chars", UNSET)
+
+ enable_signup = d.pop("enable_signup", UNSET)
+
+ enable_email_password = d.pop("enable_email_password", UNSET)
+
+ rate_limit_signup = d.pop("rate_limit_signup", UNSET)
+
+ rate_limit_signin = d.pop("rate_limit_signin", UNSET)
+
+ rate_limit_token_refresh = d.pop("rate_limit_token_refresh", UNSET)
+
+ cors_allow_credentials = d.pop("cors_allow_credentials", UNSET)
+
+ cors_max_age = d.pop("cors_max_age", UNSET)
+
+ enable_anonymous_signins = d.pop("enable_anonymous_signins", UNSET)
+
+ allowed_email_domains = cast(list[str], d.pop("allowed_email_domains", UNSET))
+
+
+ _allowed_email_domains_mode = d.pop("allowed_email_domains_mode", UNSET)
+ allowed_email_domains_mode: UpdateAuthConfigRequestAllowedEmailDomainsMode | Unset
+ if isinstance(_allowed_email_domains_mode, Unset):
+ allowed_email_domains_mode = UNSET
+ else:
+ allowed_email_domains_mode = check_update_auth_config_request_allowed_email_domains_mode(_allowed_email_domains_mode)
+
+
+
+
+ allow_password_reset = d.pop("allow_password_reset", UNSET)
+
+ password_reset_timeout = d.pop("password_reset_timeout", UNSET)
+
+ max_password_history = d.pop("max_password_history", UNSET)
+
+ require_email_confirmation = d.pop("require_email_confirmation", UNSET)
+
+ email_confirmation_timeout = d.pop("email_confirmation_timeout", UNSET)
+
+ auto_link_verified_oauth = d.pop("auto_link_verified_oauth", UNSET)
+
+ email_enabled = d.pop("email_enabled", UNSET)
+
+ email_from_address = d.pop("email_from_address", UNSET)
+
+ email_from_name = d.pop("email_from_name", UNSET)
+
+ smtp_host = d.pop("smtp_host", UNSET)
+
+ smtp_port = d.pop("smtp_port", UNSET)
+
+ smtp_username = d.pop("smtp_username", UNSET)
+
+ smtp_password = d.pop("smtp_password", UNSET)
+
+ smtp_use_tls = d.pop("smtp_use_tls", UNSET)
+
+ email_confirmation_subject = d.pop("email_confirmation_subject", UNSET)
+
+ email_password_reset_subject = d.pop("email_password_reset_subject", UNSET)
+
+ email_password_changed_subject = d.pop("email_password_changed_subject", UNSET)
+
+ managed_auth_enabled = d.pop("managed_auth_enabled", UNSET)
+
+ post_auth_redirect_url = d.pop("post_auth_redirect_url", UNSET)
+
+ allowed_redirect_urls = cast(list[str], d.pop("allowed_redirect_urls", UNSET))
+
+
+ post_logout_redirect_url = d.pop("post_logout_redirect_url", UNSET)
+
+ device_verification_url = d.pop("device_verification_url", UNSET)
+
+ update_auth_config_request = cls(
+ access_token_lifetime=access_token_lifetime,
+ refresh_token_lifetime=refresh_token_lifetime,
+ inactivity_timeout=inactivity_timeout,
+ max_session_duration=max_session_duration,
+ min_password_length=min_password_length,
+ require_uppercase=require_uppercase,
+ require_lowercase=require_lowercase,
+ require_numbers=require_numbers,
+ require_special_chars=require_special_chars,
+ enable_signup=enable_signup,
+ enable_email_password=enable_email_password,
+ rate_limit_signup=rate_limit_signup,
+ rate_limit_signin=rate_limit_signin,
+ rate_limit_token_refresh=rate_limit_token_refresh,
+ cors_allow_credentials=cors_allow_credentials,
+ cors_max_age=cors_max_age,
+ enable_anonymous_signins=enable_anonymous_signins,
+ allowed_email_domains=allowed_email_domains,
+ allowed_email_domains_mode=allowed_email_domains_mode,
+ allow_password_reset=allow_password_reset,
+ password_reset_timeout=password_reset_timeout,
+ max_password_history=max_password_history,
+ require_email_confirmation=require_email_confirmation,
+ email_confirmation_timeout=email_confirmation_timeout,
+ auto_link_verified_oauth=auto_link_verified_oauth,
+ email_enabled=email_enabled,
+ email_from_address=email_from_address,
+ email_from_name=email_from_name,
+ smtp_host=smtp_host,
+ smtp_port=smtp_port,
+ smtp_username=smtp_username,
+ smtp_password=smtp_password,
+ smtp_use_tls=smtp_use_tls,
+ email_confirmation_subject=email_confirmation_subject,
+ email_password_reset_subject=email_password_reset_subject,
+ email_password_changed_subject=email_password_changed_subject,
+ managed_auth_enabled=managed_auth_enabled,
+ post_auth_redirect_url=post_auth_redirect_url,
+ allowed_redirect_urls=allowed_redirect_urls,
+ post_logout_redirect_url=post_logout_redirect_url,
+ device_verification_url=device_verification_url,
+ )
+
+
+ update_auth_config_request.additional_properties = d
+ return update_auth_config_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_auth_config_request_allowed_email_domains_mode.py b/src/volcano_sdk/_generated/models/update_auth_config_request_allowed_email_domains_mode.py
new file mode 100644
index 00000000..c82650b8
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_auth_config_request_allowed_email_domains_mode.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+UpdateAuthConfigRequestAllowedEmailDomainsMode = Literal['disabled', 'signup', 'signup_and_signin']
+
+UPDATE_AUTH_CONFIG_REQUEST_ALLOWED_EMAIL_DOMAINS_MODE_VALUES: set[UpdateAuthConfigRequestAllowedEmailDomainsMode] = { 'disabled', 'signup', 'signup_and_signin', }
+
+def check_update_auth_config_request_allowed_email_domains_mode(value: str) -> UpdateAuthConfigRequestAllowedEmailDomainsMode:
+ if value in UPDATE_AUTH_CONFIG_REQUEST_ALLOWED_EMAIL_DOMAINS_MODE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {UPDATE_AUTH_CONFIG_REQUEST_ALLOWED_EMAIL_DOMAINS_MODE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/update_auth_hosted_page_request.py b/src/volcano_sdk/_generated/models/update_auth_hosted_page_request.py
new file mode 100644
index 00000000..18f54bb4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_auth_hosted_page_request.py
@@ -0,0 +1,86 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateAuthHostedPageRequest")
+
+
+
+@_attrs_define
+class UpdateAuthHostedPageRequest:
+ """
+ Attributes:
+ html (str): Raw HTML markup for the page. Max 256 KiB.
+ css (str | Unset): Optional CSS injected at render time. Max 256 KiB.
+ """
+
+ html: str
+ css: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ html = self.html
+
+ css = self.css
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "html": html,
+ })
+ if css is not UNSET:
+ field_dict["css"] = css
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ html = d.pop("html")
+
+ css = d.pop("css", UNSET)
+
+ update_auth_hosted_page_request = cls(
+ html=html,
+ css=css,
+ )
+
+
+ update_auth_hosted_page_request.additional_properties = d
+ return update_auth_hosted_page_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_database_branch_request.py b/src/volcano_sdk/_generated/models/update_database_branch_request.py
new file mode 100644
index 00000000..e5b429c6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_database_branch_request.py
@@ -0,0 +1,77 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateDatabaseBranchRequest")
+
+
+
+@_attrs_define
+class UpdateDatabaseBranchRequest:
+ """ Replace the branch's lifetime and restart its countdown from now.
+
+ Attributes:
+ ttl_seconds (int): The new lifetime, between one hour and 30 days. Example: 86400.
+ """
+
+ ttl_seconds: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ ttl_seconds = self.ttl_seconds
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "ttl_seconds": ttl_seconds,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ ttl_seconds = d.pop("ttl_seconds")
+
+ update_database_branch_request = cls(
+ ttl_seconds=ttl_seconds,
+ )
+
+
+ update_database_branch_request.additional_properties = d
+ return update_database_branch_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_database_type_request.py b/src/volcano_sdk/_generated/models/update_database_type_request.py
new file mode 100644
index 00000000..e81e004c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_database_type_request.py
@@ -0,0 +1,83 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.update_database_type_request_database_type import check_update_database_type_request_database_type
+from ..models.update_database_type_request_database_type import UpdateDatabaseTypeRequestDatabaseType
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateDatabaseTypeRequest")
+
+
+
+@_attrs_define
+class UpdateDatabaseTypeRequest:
+ """ Update database compute size tier
+
+ Attributes:
+ database_type (UpdateDatabaseTypeRequestDatabaseType): New compute size tier Example: volcano-db-m.
+ """
+
+ database_type: UpdateDatabaseTypeRequestDatabaseType
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ database_type: str = self.database_type
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "database_type": database_type,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ database_type = check_update_database_type_request_database_type(d.pop("database_type"))
+
+
+
+
+ update_database_type_request = cls(
+ database_type=database_type,
+ )
+
+
+ update_database_type_request.additional_properties = d
+ return update_database_type_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_database_type_request_database_type.py b/src/volcano_sdk/_generated/models/update_database_type_request_database_type.py
new file mode 100644
index 00000000..fd2bea48
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_database_type_request_database_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+UpdateDatabaseTypeRequestDatabaseType = Literal['volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs']
+
+UPDATE_DATABASE_TYPE_REQUEST_DATABASE_TYPE_VALUES: set[UpdateDatabaseTypeRequestDatabaseType] = { 'volcano-db-2xl', 'volcano-db-l', 'volcano-db-m', 'volcano-db-s', 'volcano-db-xl', 'volcano-db-xs', }
+
+def check_update_database_type_request_database_type(value: str) -> UpdateDatabaseTypeRequestDatabaseType:
+ if value in UPDATE_DATABASE_TYPE_REQUEST_DATABASE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {UPDATE_DATABASE_TYPE_REQUEST_DATABASE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/update_email_template_request.py b/src/volcano_sdk/_generated/models/update_email_template_request.py
new file mode 100644
index 00000000..dc903645
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_email_template_request.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateEmailTemplateRequest")
+
+
+
+@_attrs_define
+class UpdateEmailTemplateRequest:
+ """
+ Attributes:
+ subject (str | Unset):
+ html_body (str | Unset):
+ text_body (str | Unset):
+ """
+
+ subject: str | Unset = UNSET
+ html_body: str | Unset = UNSET
+ text_body: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ subject = self.subject
+
+ html_body = self.html_body
+
+ text_body = self.text_body
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if subject is not UNSET:
+ field_dict["subject"] = subject
+ if html_body is not UNSET:
+ field_dict["html_body"] = html_body
+ if text_body is not UNSET:
+ field_dict["text_body"] = text_body
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ subject = d.pop("subject", UNSET)
+
+ html_body = d.pop("html_body", UNSET)
+
+ text_body = d.pop("text_body", UNSET)
+
+ update_email_template_request = cls(
+ subject=subject,
+ html_body=html_body,
+ text_body=text_body,
+ )
+
+
+ update_email_template_request.additional_properties = d
+ return update_email_template_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_email_template_type.py b/src/volcano_sdk/_generated/models/update_email_template_type.py
new file mode 100644
index 00000000..6fdb72c7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_email_template_type.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+UpdateEmailTemplateType = Literal['confirmation', 'password_changed', 'password_reset', 'welcome']
+
+UPDATE_EMAIL_TEMPLATE_TYPE_VALUES: set[UpdateEmailTemplateType] = { 'confirmation', 'password_changed', 'password_reset', 'welcome', }
+
+def check_update_email_template_type(value: str) -> UpdateEmailTemplateType:
+ if value in UPDATE_EMAIL_TEMPLATE_TYPE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {UPDATE_EMAIL_TEMPLATE_TYPE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/update_function_request.py b/src/volcano_sdk/_generated/models/update_function_request.py
new file mode 100644
index 00000000..f601febc
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_function_request.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateFunctionRequest")
+
+
+
+@_attrs_define
+class UpdateFunctionRequest:
+ """
+ Attributes:
+ is_public (bool): Function visibility for anon-key invocation.
+ - `false` (default): private function
+ - `true`: public function (anon keys with `functions.invoke` can invoke)
+ """
+
+ is_public: bool
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ is_public = self.is_public
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "is_public": is_public,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ is_public = d.pop("is_public")
+
+ update_function_request = cls(
+ is_public=is_public,
+ )
+
+
+ update_function_request.additional_properties = d
+ return update_function_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_function_scheduler_request.py b/src/volcano_sdk/_generated/models/update_function_scheduler_request.py
new file mode 100644
index 00000000..e38d4dc0
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_function_scheduler_request.py
@@ -0,0 +1,147 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+if TYPE_CHECKING:
+ from ..models.schedule_request import ScheduleRequest
+ from ..models.update_function_scheduler_request_payload import UpdateFunctionSchedulerRequestPayload
+
+
+
+
+
+T = TypeVar("T", bound="UpdateFunctionSchedulerRequest")
+
+
+
+@_attrs_define
+class UpdateFunctionSchedulerRequest:
+ """
+ Attributes:
+ name (str | Unset):
+ enabled (bool | Unset):
+ schedule (ScheduleRequest | Unset):
+ payload (UpdateFunctionSchedulerRequestPayload | Unset):
+ regions (list[str] | Unset):
+ """
+
+ name: str | Unset = UNSET
+ enabled: bool | Unset = UNSET
+ schedule: ScheduleRequest | Unset = UNSET
+ payload: UpdateFunctionSchedulerRequestPayload | Unset = UNSET
+ regions: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.schedule_request import ScheduleRequest
+ from ..models.update_function_scheduler_request_payload import UpdateFunctionSchedulerRequestPayload
+ name = self.name
+
+ enabled = self.enabled
+
+ schedule: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.schedule, Unset):
+ schedule = self.schedule.to_dict()
+
+ payload: dict[str, Any] | Unset = UNSET
+ if not isinstance(self.payload, Unset):
+ payload = self.payload.to_dict()
+
+ regions: list[str] | Unset = UNSET
+ if not isinstance(self.regions, Unset):
+ regions = self.regions
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if name is not UNSET:
+ field_dict["name"] = name
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if schedule is not UNSET:
+ field_dict["schedule"] = schedule
+ if payload is not UNSET:
+ field_dict["payload"] = payload
+ if regions is not UNSET:
+ field_dict["regions"] = regions
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.schedule_request import ScheduleRequest
+ from ..models.update_function_scheduler_request_payload import UpdateFunctionSchedulerRequestPayload
+ d = dict(src_dict)
+ name = d.pop("name", UNSET)
+
+ enabled = d.pop("enabled", UNSET)
+
+ _schedule = d.pop("schedule", UNSET)
+ schedule: ScheduleRequest | Unset
+ if isinstance(_schedule, Unset):
+ schedule = UNSET
+ else:
+ schedule = ScheduleRequest.from_dict(_schedule)
+
+
+
+
+ _payload = d.pop("payload", UNSET)
+ payload: UpdateFunctionSchedulerRequestPayload | Unset
+ if isinstance(_payload, Unset):
+ payload = UNSET
+ else:
+ payload = UpdateFunctionSchedulerRequestPayload.from_dict(_payload)
+
+
+
+
+ regions = cast(list[str], d.pop("regions", UNSET))
+
+
+ update_function_scheduler_request = cls(
+ name=name,
+ enabled=enabled,
+ schedule=schedule,
+ payload=payload,
+ regions=regions,
+ )
+
+
+ update_function_scheduler_request.additional_properties = d
+ return update_function_scheduler_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_function_scheduler_request_payload.py b/src/volcano_sdk/_generated/models/update_function_scheduler_request_payload.py
new file mode 100644
index 00000000..8fcdbbe3
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_function_scheduler_request_payload.py
@@ -0,0 +1,65 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateFunctionSchedulerRequestPayload")
+
+
+
+@_attrs_define
+class UpdateFunctionSchedulerRequestPayload:
+ """
+ """
+
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ update_function_scheduler_request_payload = cls(
+ )
+
+
+ update_function_scheduler_request_payload.additional_properties = d
+ return update_function_scheduler_request_payload
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_o_auth_config_provider.py b/src/volcano_sdk/_generated/models/update_o_auth_config_provider.py
new file mode 100644
index 00000000..c3e781f7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_o_auth_config_provider.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+UpdateOAuthConfigProvider = Literal['apple', 'device', 'github', 'google', 'microsoft']
+
+UPDATE_O_AUTH_CONFIG_PROVIDER_VALUES: set[UpdateOAuthConfigProvider] = { 'apple', 'device', 'github', 'google', 'microsoft', }
+
+def check_update_o_auth_config_provider(value: str) -> UpdateOAuthConfigProvider:
+ if value in UPDATE_O_AUTH_CONFIG_PROVIDER_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {UPDATE_O_AUTH_CONFIG_PROVIDER_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/update_o_auth_config_request.py b/src/volcano_sdk/_generated/models/update_o_auth_config_request.py
new file mode 100644
index 00000000..c920dba5
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_o_auth_config_request.py
@@ -0,0 +1,120 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateOAuthConfigRequest")
+
+
+
+@_attrs_define
+class UpdateOAuthConfigRequest:
+ """
+ Attributes:
+ client_id (str | Unset): Supported for non-device providers. Not supported for `provider=device`.
+ client_secret (str | Unset): Supported for non-device providers. Not supported for `provider=device`.
+ redirect_url (str | Unset):
+ scopes (list[str] | Unset):
+ enabled (bool | Unset):
+ """
+
+ client_id: str | Unset = UNSET
+ client_secret: str | Unset = UNSET
+ redirect_url: str | Unset = UNSET
+ scopes: list[str] | Unset = UNSET
+ enabled: bool | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ redirect_url = self.redirect_url
+
+ scopes: list[str] | Unset = UNSET
+ if not isinstance(self.scopes, Unset):
+ scopes = self.scopes
+
+
+
+ enabled = self.enabled
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if client_id is not UNSET:
+ field_dict["client_id"] = client_id
+ if client_secret is not UNSET:
+ field_dict["client_secret"] = client_secret
+ if redirect_url is not UNSET:
+ field_dict["redirect_url"] = redirect_url
+ if scopes is not UNSET:
+ field_dict["scopes"] = scopes
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ client_id = d.pop("client_id", UNSET)
+
+ client_secret = d.pop("client_secret", UNSET)
+
+ redirect_url = d.pop("redirect_url", UNSET)
+
+ scopes = cast(list[str], d.pop("scopes", UNSET))
+
+
+ enabled = d.pop("enabled", UNSET)
+
+ update_o_auth_config_request = cls(
+ client_id=client_id,
+ client_secret=client_secret,
+ redirect_url=redirect_url,
+ scopes=scopes,
+ enabled=enabled,
+ )
+
+
+ update_o_auth_config_request.additional_properties = d
+ return update_o_auth_config_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_project_git_deploy_settings_request.py b/src/volcano_sdk/_generated/models/update_project_git_deploy_settings_request.py
new file mode 100644
index 00000000..9b0a713e
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_project_git_deploy_settings_request.py
@@ -0,0 +1,105 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateProjectGitDeploySettingsRequest")
+
+
+
+@_attrs_define
+class UpdateProjectGitDeploySettingsRequest:
+ """ Full replace of a project's Git auto-deploy settings.
+
+ Attributes:
+ auto_deploy_enabled (bool):
+ deploy_functions (bool):
+ frontend_name (str | Unset): Frontend to deploy on push. Omit or empty to deploy no frontend.
+ frontend_app_root (str | Unset): App root the frontend builds from. Requires frontend_name; omit for the repo
+ root.
+ """
+
+ auto_deploy_enabled: bool
+ deploy_functions: bool
+ frontend_name: str | Unset = UNSET
+ frontend_app_root: str | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ auto_deploy_enabled = self.auto_deploy_enabled
+
+ deploy_functions = self.deploy_functions
+
+ frontend_name = self.frontend_name
+
+ frontend_app_root = self.frontend_app_root
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "auto_deploy_enabled": auto_deploy_enabled,
+ "deploy_functions": deploy_functions,
+ })
+ if frontend_name is not UNSET:
+ field_dict["frontend_name"] = frontend_name
+ if frontend_app_root is not UNSET:
+ field_dict["frontend_app_root"] = frontend_app_root
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ auto_deploy_enabled = d.pop("auto_deploy_enabled")
+
+ deploy_functions = d.pop("deploy_functions")
+
+ frontend_name = d.pop("frontend_name", UNSET)
+
+ frontend_app_root = d.pop("frontend_app_root", UNSET)
+
+ update_project_git_deploy_settings_request = cls(
+ auto_deploy_enabled=auto_deploy_enabled,
+ deploy_functions=deploy_functions,
+ frontend_name=frontend_name,
+ frontend_app_root=frontend_app_root,
+ )
+
+
+ update_project_git_deploy_settings_request.additional_properties = d
+ return update_project_git_deploy_settings_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_project_request.py b/src/volcano_sdk/_generated/models/update_project_request.py
new file mode 100644
index 00000000..b8e0b538
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_project_request.py
@@ -0,0 +1,107 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateProjectRequest")
+
+
+
+@_attrs_define
+class UpdateProjectRequest:
+ """ Update mutable project fields (name and/or region policy)
+
+ Attributes:
+ name (str | Unset): Example: my-awesome-app-renamed.
+ all_regions (bool | Unset): If omitted and `selected_regions` is also omitted, existing region policy is
+ preserved.
+ If `selected_regions` is provided without `all_regions`, it is treated as subset mode.
+ selected_regions (list[str] | Unset): Region subset for project deployments.
+ Provide with `all_regions=false`.
+ Example: ['us-east-1'].
+ """
+
+ name: str | Unset = UNSET
+ all_regions: bool | Unset = UNSET
+ selected_regions: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ name = self.name
+
+ all_regions = self.all_regions
+
+ selected_regions: list[str] | Unset = UNSET
+ if not isinstance(self.selected_regions, Unset):
+ selected_regions = self.selected_regions
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if name is not UNSET:
+ field_dict["name"] = name
+ if all_regions is not UNSET:
+ field_dict["all_regions"] = all_regions
+ if selected_regions is not UNSET:
+ field_dict["selected_regions"] = selected_regions
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ name = d.pop("name", UNSET)
+
+ all_regions = d.pop("all_regions", UNSET)
+
+ selected_regions = cast(list[str], d.pop("selected_regions", UNSET))
+
+
+ update_project_request = cls(
+ name=name,
+ all_regions=all_regions,
+ selected_regions=selected_regions,
+ )
+
+
+ update_project_request.additional_properties = d
+ return update_project_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_realtime_config_request.py b/src/volcano_sdk/_generated/models/update_realtime_config_request.py
new file mode 100644
index 00000000..b9e5c546
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_realtime_config_request.py
@@ -0,0 +1,107 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateRealtimeConfigRequest")
+
+
+
+@_attrs_define
+class UpdateRealtimeConfigRequest:
+ """ Request to update realtime configuration.
+ Limits (message size, channels per connection) are plan-based and cannot be configured.
+
+ Attributes:
+ enabled (bool | Unset): Whether realtime is enabled for this project
+ broadcast_enabled (bool | Unset): Whether broadcast channels are enabled
+ presence_enabled (bool | Unset): Whether presence tracking is enabled
+ postgres_changes_enabled (bool | Unset): Whether Postgres change notifications are enabled
+ """
+
+ enabled: bool | Unset = UNSET
+ broadcast_enabled: bool | Unset = UNSET
+ presence_enabled: bool | Unset = UNSET
+ postgres_changes_enabled: bool | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ enabled = self.enabled
+
+ broadcast_enabled = self.broadcast_enabled
+
+ presence_enabled = self.presence_enabled
+
+ postgres_changes_enabled = self.postgres_changes_enabled
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if enabled is not UNSET:
+ field_dict["enabled"] = enabled
+ if broadcast_enabled is not UNSET:
+ field_dict["broadcast_enabled"] = broadcast_enabled
+ if presence_enabled is not UNSET:
+ field_dict["presence_enabled"] = presence_enabled
+ if postgres_changes_enabled is not UNSET:
+ field_dict["postgres_changes_enabled"] = postgres_changes_enabled
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ enabled = d.pop("enabled", UNSET)
+
+ broadcast_enabled = d.pop("broadcast_enabled", UNSET)
+
+ presence_enabled = d.pop("presence_enabled", UNSET)
+
+ postgres_changes_enabled = d.pop("postgres_changes_enabled", UNSET)
+
+ update_realtime_config_request = cls(
+ enabled=enabled,
+ broadcast_enabled=broadcast_enabled,
+ presence_enabled=presence_enabled,
+ postgres_changes_enabled=postgres_changes_enabled,
+ )
+
+
+ update_realtime_config_request.additional_properties = d
+ return update_realtime_config_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_storage_bucket_request.py b/src/volcano_sdk/_generated/models/update_storage_bucket_request.py
new file mode 100644
index 00000000..68435465
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_storage_bucket_request.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+from typing import cast
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateStorageBucketRequest")
+
+
+
+@_attrs_define
+class UpdateStorageBucketRequest:
+ """
+ Attributes:
+ file_size_limit (int | Unset):
+ allowed_mime_types (list[str] | Unset):
+ """
+
+ file_size_limit: int | Unset = UNSET
+ allowed_mime_types: list[str] | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ file_size_limit = self.file_size_limit
+
+ allowed_mime_types: list[str] | Unset = UNSET
+ if not isinstance(self.allowed_mime_types, Unset):
+ allowed_mime_types = self.allowed_mime_types
+
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if file_size_limit is not UNSET:
+ field_dict["file_size_limit"] = file_size_limit
+ if allowed_mime_types is not UNSET:
+ field_dict["allowed_mime_types"] = allowed_mime_types
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ file_size_limit = d.pop("file_size_limit", UNSET)
+
+ allowed_mime_types = cast(list[str], d.pop("allowed_mime_types", UNSET))
+
+
+ update_storage_bucket_request = cls(
+ file_size_limit=file_size_limit,
+ allowed_mime_types=allowed_mime_types,
+ )
+
+
+ update_storage_bucket_request.additional_properties = d
+ return update_storage_bucket_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/update_variable_request.py b/src/volcano_sdk/_generated/models/update_variable_request.py
new file mode 100644
index 00000000..a8c8e6d4
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/update_variable_request.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+
+T = TypeVar("T", bound="UpdateVariableRequest")
+
+
+
+@_attrs_define
+class UpdateVariableRequest:
+ """
+ Attributes:
+ value (str):
+ """
+
+ value: str
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ value = d.pop("value")
+
+ update_variable_request = cls(
+ value=value,
+ )
+
+
+ update_variable_request.additional_properties = d
+ return update_variable_request
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/upload_project_logo_body.py b/src/volcano_sdk/_generated/models/upload_project_logo_body.py
new file mode 100644
index 00000000..a8c053cb
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/upload_project_logo_body.py
@@ -0,0 +1,101 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+import json
+from .. import types
+
+from ..types import UNSET, Unset
+
+from ..types import File, FileTypes
+from io import BytesIO
+
+
+
+
+
+
+T = TypeVar("T", bound="UploadProjectLogoBody")
+
+
+
+@_attrs_define
+class UploadProjectLogoBody:
+ """
+ Attributes:
+ logo (File): Logo image (PNG, JPEG, GIF, WebP, or SVG; max 2 MB)
+ """
+
+ logo: File
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ logo = self.logo.to_tuple()
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "logo": logo,
+ })
+
+ return field_dict
+
+
+ def to_multipart(self) -> types.RequestFiles:
+ files: types.RequestFiles = []
+
+ files.append(("logo", self.logo.to_tuple()))
+
+
+
+
+ for prop_name, prop in self.additional_properties.items():
+ files.append((prop_name, (None, str(prop).encode(), "text/plain")))
+
+
+
+ return files
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ logo = File(
+ payload = BytesIO(d.pop("logo"))
+ )
+
+
+
+
+ upload_project_logo_body = cls(
+ logo=logo,
+ )
+
+
+ upload_project_logo_body.additional_properties = d
+ return upload_project_logo_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/upload_session_part.py b/src/volcano_sdk/_generated/models/upload_session_part.py
new file mode 100644
index 00000000..45594d6b
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/upload_session_part.py
@@ -0,0 +1,97 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..types import UNSET, Unset
+
+
+
+
+
+
+T = TypeVar("T", bound="UploadSessionPart")
+
+
+
+@_attrs_define
+class UploadSessionPart:
+ """ Information about an uploaded part
+
+ Attributes:
+ part_number (int | Unset): Part number (1-10000)
+ etag (str | Unset): ETag of the uploaded part
+ size (int | Unset): Size of the part in bytes
+ """
+
+ part_number: int | Unset = UNSET
+ etag: str | Unset = UNSET
+ size: int | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ part_number = self.part_number
+
+ etag = self.etag
+
+ size = self.size
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if part_number is not UNSET:
+ field_dict["part_number"] = part_number
+ if etag is not UNSET:
+ field_dict["etag"] = etag
+ if size is not UNSET:
+ field_dict["size"] = size
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ part_number = d.pop("part_number", UNSET)
+
+ etag = d.pop("etag", UNSET)
+
+ size = d.pop("size", UNSET)
+
+ upload_session_part = cls(
+ part_number=part_number,
+ etag=etag,
+ size=size,
+ )
+
+
+ upload_session_part.additional_properties = d
+ return upload_session_part
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/upload_session_status_response.py b/src/volcano_sdk/_generated/models/upload_session_status_response.py
new file mode 100644
index 00000000..ce01391d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/upload_session_status_response.py
@@ -0,0 +1,234 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.upload_session_status_response_status import check_upload_session_status_response_status
+from ..models.upload_session_status_response_status import UploadSessionStatusResponseStatus
+from ..types import UNSET, Unset
+from typing import cast
+import datetime
+
+if TYPE_CHECKING:
+ from ..models.upload_session_part import UploadSessionPart
+
+
+
+
+
+T = TypeVar("T", bound="UploadSessionStatusResponse")
+
+
+
+@_attrs_define
+class UploadSessionStatusResponse:
+ """ Status of an upload session
+
+ Attributes:
+ session_id (str | Unset): Upload session ID
+ status (UploadSessionStatusResponseStatus | Unset): Current status of the upload
+ path (str | Unset): Target file path
+ content_type (str | Unset): MIME type
+ total_size (int | Unset): Total file size in bytes
+ part_size (int | Unset): Size of each part (except last)
+ total_parts (int | Unset): Total number of parts
+ parts_uploaded (int | Unset): Number of parts uploaded
+ bytes_uploaded (int | Unset): Total bytes uploaded so far
+ parts (list[UploadSessionPart] | Unset): List of uploaded parts (for resume)
+ expires_at (datetime.datetime | Unset): Session expiry time
+ created_at (datetime.datetime | Unset): Session creation time
+ """
+
+ session_id: str | Unset = UNSET
+ status: UploadSessionStatusResponseStatus | Unset = UNSET
+ path: str | Unset = UNSET
+ content_type: str | Unset = UNSET
+ total_size: int | Unset = UNSET
+ part_size: int | Unset = UNSET
+ total_parts: int | Unset = UNSET
+ parts_uploaded: int | Unset = UNSET
+ bytes_uploaded: int | Unset = UNSET
+ parts: list[UploadSessionPart] | Unset = UNSET
+ expires_at: datetime.datetime | Unset = UNSET
+ created_at: datetime.datetime | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ from ..models.upload_session_part import UploadSessionPart
+ session_id = self.session_id
+
+ status: str | Unset = UNSET
+ if not isinstance(self.status, Unset):
+ status = self.status
+
+
+ path = self.path
+
+ content_type = self.content_type
+
+ total_size = self.total_size
+
+ part_size = self.part_size
+
+ total_parts = self.total_parts
+
+ parts_uploaded = self.parts_uploaded
+
+ bytes_uploaded = self.bytes_uploaded
+
+ parts: list[dict[str, Any]] | Unset = UNSET
+ if not isinstance(self.parts, Unset):
+ parts = []
+ for parts_item_data in self.parts:
+ parts_item = parts_item_data.to_dict()
+ parts.append(parts_item)
+
+
+
+ expires_at: str | Unset = UNSET
+ if not isinstance(self.expires_at, Unset):
+ expires_at = self.expires_at.isoformat()
+
+ created_at: str | Unset = UNSET
+ if not isinstance(self.created_at, Unset):
+ created_at = self.created_at.isoformat()
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ })
+ if session_id is not UNSET:
+ field_dict["session_id"] = session_id
+ if status is not UNSET:
+ field_dict["status"] = status
+ if path is not UNSET:
+ field_dict["path"] = path
+ if content_type is not UNSET:
+ field_dict["content_type"] = content_type
+ if total_size is not UNSET:
+ field_dict["total_size"] = total_size
+ if part_size is not UNSET:
+ field_dict["part_size"] = part_size
+ if total_parts is not UNSET:
+ field_dict["total_parts"] = total_parts
+ if parts_uploaded is not UNSET:
+ field_dict["parts_uploaded"] = parts_uploaded
+ if bytes_uploaded is not UNSET:
+ field_dict["bytes_uploaded"] = bytes_uploaded
+ if parts is not UNSET:
+ field_dict["parts"] = parts
+ if expires_at is not UNSET:
+ field_dict["expires_at"] = expires_at
+ if created_at is not UNSET:
+ field_dict["created_at"] = created_at
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ from ..models.upload_session_part import UploadSessionPart
+ d = dict(src_dict)
+ session_id = d.pop("session_id", UNSET)
+
+ _status = d.pop("status", UNSET)
+ status: UploadSessionStatusResponseStatus | Unset
+ if isinstance(_status, Unset):
+ status = UNSET
+ else:
+ status = check_upload_session_status_response_status(_status)
+
+
+
+
+ path = d.pop("path", UNSET)
+
+ content_type = d.pop("content_type", UNSET)
+
+ total_size = d.pop("total_size", UNSET)
+
+ part_size = d.pop("part_size", UNSET)
+
+ total_parts = d.pop("total_parts", UNSET)
+
+ parts_uploaded = d.pop("parts_uploaded", UNSET)
+
+ bytes_uploaded = d.pop("bytes_uploaded", UNSET)
+
+ _parts = d.pop("parts", UNSET)
+ parts: list[UploadSessionPart] | Unset = UNSET
+ if _parts is not UNSET:
+ parts = []
+ for parts_item_data in _parts:
+ parts_item = UploadSessionPart.from_dict(parts_item_data)
+
+
+
+ parts.append(parts_item)
+
+
+ _expires_at = d.pop("expires_at", UNSET)
+ expires_at: datetime.datetime | Unset
+ if isinstance(_expires_at, Unset):
+ expires_at = UNSET
+ else:
+ expires_at = datetime.datetime.fromisoformat(_expires_at)
+
+
+
+
+ _created_at = d.pop("created_at", UNSET)
+ created_at: datetime.datetime | Unset
+ if isinstance(_created_at, Unset):
+ created_at = UNSET
+ else:
+ created_at = datetime.datetime.fromisoformat(_created_at)
+
+
+
+
+ upload_session_status_response = cls(
+ session_id=session_id,
+ status=status,
+ path=path,
+ content_type=content_type,
+ total_size=total_size,
+ part_size=part_size,
+ total_parts=total_parts,
+ parts_uploaded=parts_uploaded,
+ bytes_uploaded=bytes_uploaded,
+ parts=parts,
+ expires_at=expires_at,
+ created_at=created_at,
+ )
+
+
+ upload_session_status_response.additional_properties = d
+ return upload_session_status_response
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/upload_session_status_response_status.py b/src/volcano_sdk/_generated/models/upload_session_status_response_status.py
new file mode 100644
index 00000000..80060e0d
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/upload_session_status_response_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+UploadSessionStatusResponseStatus = Literal['aborted', 'completed', 'completing', 'pending', 'uploading']
+
+UPLOAD_SESSION_STATUS_RESPONSE_STATUS_VALUES: set[UploadSessionStatusResponseStatus] = { 'aborted', 'completed', 'completing', 'pending', 'uploading', }
+
+def check_upload_session_status_response_status(value: str) -> UploadSessionStatusResponseStatus:
+ if value in UPLOAD_SESSION_STATUS_RESPONSE_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {UPLOAD_SESSION_STATUS_RESPONSE_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/upload_storage_object_files_body.py b/src/volcano_sdk/_generated/models/upload_storage_object_files_body.py
new file mode 100644
index 00000000..bd2921b6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/upload_storage_object_files_body.py
@@ -0,0 +1,101 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+import json
+from .. import types
+
+from ..types import UNSET, Unset
+
+from ..types import File, FileTypes
+from io import BytesIO
+
+
+
+
+
+
+T = TypeVar("T", bound="UploadStorageObjectFilesBody")
+
+
+
+@_attrs_define
+class UploadStorageObjectFilesBody:
+ """
+ Attributes:
+ file (File): File to upload (simple upload)
+ """
+
+ file: File
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ file = self.file.to_tuple()
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "file": file,
+ })
+
+ return field_dict
+
+
+ def to_multipart(self) -> types.RequestFiles:
+ files: types.RequestFiles = []
+
+ files.append(("file", self.file.to_tuple()))
+
+
+
+
+ for prop_name, prop in self.additional_properties.items():
+ files.append((prop_name, (None, str(prop).encode(), "text/plain")))
+
+
+
+ return files
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ file = File(
+ payload = BytesIO(d.pop("file"))
+ )
+
+
+
+
+ upload_storage_object_files_body = cls(
+ file=file,
+ )
+
+
+ upload_storage_object_files_body.additional_properties = d
+ return upload_storage_object_files_body
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/upload_storage_object_x_upload_complete.py b/src/volcano_sdk/_generated/models/upload_storage_object_x_upload_complete.py
new file mode 100644
index 00000000..0893f2b6
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/upload_storage_object_x_upload_complete.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+UploadStorageObjectXUploadComplete = Literal['true']
+
+UPLOAD_STORAGE_OBJECT_X_UPLOAD_COMPLETE_VALUES: set[UploadStorageObjectXUploadComplete] = { 'true', }
+
+def check_upload_storage_object_x_upload_complete(value: str) -> UploadStorageObjectXUploadComplete:
+ if value in UPLOAD_STORAGE_OBJECT_X_UPLOAD_COMPLETE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {UPLOAD_STORAGE_OBJECT_X_UPLOAD_COMPLETE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/usage_data_point.py b/src/volcano_sdk/_generated/models/usage_data_point.py
new file mode 100644
index 00000000..ac6f72f9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/usage_data_point.py
@@ -0,0 +1,90 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from typing import cast
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="UsageDataPoint")
+
+
+
+@_attrs_define
+class UsageDataPoint:
+ """ A single timestamped usage value.
+
+ Attributes:
+ timestamp (datetime.datetime): UTC timestamp for the data point
+ value (int): Usage value at the timestamp
+ """
+
+ timestamp: datetime.datetime
+ value: int
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ timestamp = self.timestamp.isoformat()
+
+ value = self.value
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "timestamp": timestamp,
+ "value": value,
+ })
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ timestamp = datetime.datetime.fromisoformat(d.pop("timestamp"))
+
+
+
+
+ value = d.pop("value")
+
+ usage_data_point = cls(
+ timestamp=timestamp,
+ value=value,
+ )
+
+
+ usage_data_point.additional_properties = d
+ return usage_data_point
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/variable.py b/src/volcano_sdk/_generated/models/variable.py
new file mode 100644
index 00000000..c3ac331c
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/variable.py
@@ -0,0 +1,216 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+from ..types import UNSET, Unset
+
+from ..models.variable_deploy_source import check_variable_deploy_source
+from ..models.variable_deploy_source import VariableDeploySource
+from ..models.variable_status import check_variable_status
+from ..models.variable_status import VariableStatus
+from ..types import UNSET, Unset
+from typing import cast
+from uuid import UUID
+import datetime
+
+
+
+
+
+
+T = TypeVar("T", bound="Variable")
+
+
+
+@_attrs_define
+class Variable:
+ """
+ Attributes:
+ id (UUID):
+ project_id (UUID):
+ name (str):
+ value (str):
+ created_at (datetime.datetime):
+ updated_at (datetime.datetime):
+ status (VariableStatus | Unset): Latest project variable propagation status, when a sync has run.
+ current_sync_id (UUID | Unset): Identifier of the latest variable propagation sync.
+ provisioning_started_at (datetime.datetime | Unset): Timestamp when the current variable propagation phase
+ started.
+ deploy_source (VariableDeploySource | Unset): What initiated the latest variable propagation sync, when one has
+ run.
+ """
+
+ id: UUID
+ project_id: UUID
+ name: str
+ value: str
+ created_at: datetime.datetime
+ updated_at: datetime.datetime
+ status: VariableStatus | Unset = UNSET
+ current_sync_id: UUID | Unset = UNSET
+ provisioning_started_at: datetime.datetime | Unset = UNSET
+ deploy_source: VariableDeploySource | Unset = UNSET
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
+
+
+
+
+
+ def to_dict(self) -> dict[str, Any]:
+ id = str(self.id)
+
+ project_id = str(self.project_id)
+
+ name = self.name
+
+ value = self.value
+
+ created_at = self.created_at.isoformat()
+
+ updated_at = self.updated_at.isoformat()
+
+ status: str | Unset = UNSET
+ if not isinstance(self.status, Unset):
+ status = self.status
+
+
+ current_sync_id: str | Unset = UNSET
+ if not isinstance(self.current_sync_id, Unset):
+ current_sync_id = str(self.current_sync_id)
+
+ provisioning_started_at: str | Unset = UNSET
+ if not isinstance(self.provisioning_started_at, Unset):
+ provisioning_started_at = self.provisioning_started_at.isoformat()
+
+ deploy_source: str | Unset = UNSET
+ if not isinstance(self.deploy_source, Unset):
+ deploy_source = self.deploy_source
+
+
+
+ field_dict: dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+ field_dict.update({
+ "id": id,
+ "project_id": project_id,
+ "name": name,
+ "value": value,
+ "created_at": created_at,
+ "updated_at": updated_at,
+ })
+ if status is not UNSET:
+ field_dict["status"] = status
+ if current_sync_id is not UNSET:
+ field_dict["current_sync_id"] = current_sync_id
+ if provisioning_started_at is not UNSET:
+ field_dict["provisioning_started_at"] = provisioning_started_at
+ if deploy_source is not UNSET:
+ field_dict["deploy_source"] = deploy_source
+
+ return field_dict
+
+
+
+ @classmethod
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
+ d = dict(src_dict)
+ id = UUID(d.pop("id"))
+
+
+
+
+ project_id = UUID(d.pop("project_id"))
+
+
+
+
+ name = d.pop("name")
+
+ value = d.pop("value")
+
+ created_at = datetime.datetime.fromisoformat(d.pop("created_at"))
+
+
+
+
+ updated_at = datetime.datetime.fromisoformat(d.pop("updated_at"))
+
+
+
+
+ _status = d.pop("status", UNSET)
+ status: VariableStatus | Unset
+ if isinstance(_status, Unset):
+ status = UNSET
+ else:
+ status = check_variable_status(_status)
+
+
+
+
+ _current_sync_id = d.pop("current_sync_id", UNSET)
+ current_sync_id: UUID | Unset
+ if isinstance(_current_sync_id, Unset):
+ current_sync_id = UNSET
+ else:
+ current_sync_id = UUID(_current_sync_id)
+
+
+
+
+ _provisioning_started_at = d.pop("provisioning_started_at", UNSET)
+ provisioning_started_at: datetime.datetime | Unset
+ if isinstance(_provisioning_started_at, Unset):
+ provisioning_started_at = UNSET
+ else:
+ provisioning_started_at = datetime.datetime.fromisoformat(_provisioning_started_at)
+
+
+
+
+ _deploy_source = d.pop("deploy_source", UNSET)
+ deploy_source: VariableDeploySource | Unset
+ if isinstance(_deploy_source, Unset):
+ deploy_source = UNSET
+ else:
+ deploy_source = check_variable_deploy_source(_deploy_source)
+
+
+
+
+ variable = cls(
+ id=id,
+ project_id=project_id,
+ name=name,
+ value=value,
+ created_at=created_at,
+ updated_at=updated_at,
+ status=status,
+ current_sync_id=current_sync_id,
+ provisioning_started_at=provisioning_started_at,
+ deploy_source=deploy_source,
+ )
+
+
+ variable.additional_properties = d
+ return variable
+
+ @property
+ def additional_keys(self) -> list[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> Any:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: Any) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/src/volcano_sdk/_generated/models/variable_deploy_source.py b/src/volcano_sdk/_generated/models/variable_deploy_source.py
new file mode 100644
index 00000000..cdd445a7
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/variable_deploy_source.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+VariableDeploySource = Literal['api', 'cli', 'git', 'system', 'unknown', 'web']
+
+VARIABLE_DEPLOY_SOURCE_VALUES: set[VariableDeploySource] = { 'api', 'cli', 'git', 'system', 'unknown', 'web', }
+
+def check_variable_deploy_source(value: str) -> VariableDeploySource:
+ if value in VARIABLE_DEPLOY_SOURCE_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {VARIABLE_DEPLOY_SOURCE_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/models/variable_status.py b/src/volcano_sdk/_generated/models/variable_status.py
new file mode 100644
index 00000000..ee385ae9
--- /dev/null
+++ b/src/volcano_sdk/_generated/models/variable_status.py
@@ -0,0 +1,10 @@
+from typing import Literal
+
+VariableStatus = Literal['active', 'failed', 'provisioning']
+
+VARIABLE_STATUS_VALUES: set[VariableStatus] = { 'active', 'failed', 'provisioning', }
+
+def check_variable_status(value: str) -> VariableStatus:
+ if value in VARIABLE_STATUS_VALUES:
+ return value
+ raise TypeError(f"Unexpected value {value!r}. Expected one of {VARIABLE_STATUS_VALUES!r}")
diff --git a/src/volcano_sdk/_generated/types.py b/src/volcano_sdk/_generated/types.py
new file mode 100644
index 00000000..f74db0ad
--- /dev/null
+++ b/src/volcano_sdk/_generated/types.py
@@ -0,0 +1,53 @@
+""" Contains some shared types for properties """
+
+from collections.abc import Mapping, MutableMapping
+from http import HTTPStatus
+from typing import BinaryIO, Generic, TypeVar, Literal, IO
+
+from attrs import define
+
+
+class Unset:
+ def __bool__(self) -> Literal[False]:
+ return False
+
+
+UNSET: Unset = Unset()
+
+# The types that `httpx.Client(files=)` can accept, copied from that library.
+FileContent = IO[bytes] | bytes | str
+FileTypes = (
+ # (filename, file (or bytes), content_type)
+ tuple[str | None, FileContent, str | None]
+ # (filename, file (or bytes), content_type, headers)
+ | tuple[str | None, FileContent, str | None, Mapping[str, str]]
+)
+RequestFiles = list[tuple[str, FileTypes]]
+
+@define
+class File:
+ """ Contains information for file uploads """
+
+ payload: BinaryIO
+ file_name: str | None = None
+ mime_type: str | None = None
+
+ def to_tuple(self) -> FileTypes:
+ """ Return a tuple representation that httpx will accept for multipart/form-data """
+ return self.file_name, self.payload, self.mime_type
+
+
+T = TypeVar("T")
+
+
+@define
+class Response(Generic[T]):
+ """ A response from an endpoint """
+
+ status_code: HTTPStatus
+ content: bytes
+ headers: MutableMapping[str, str]
+ parsed: T | None
+
+
+__all__ = ["UNSET", "File", "FileTypes", "RequestFiles", "Response", "Unset"]
diff --git a/src/volcano_sdk/_transport.py b/src/volcano_sdk/_transport.py
new file mode 100644
index 00000000..99b100ef
--- /dev/null
+++ b/src/volcano_sdk/_transport.py
@@ -0,0 +1,297 @@
+from __future__ import annotations
+
+import json
+from collections.abc import Callable, Mapping
+from dataclasses import dataclass
+from io import BytesIO
+from pathlib import PurePosixPath
+from typing import Any, Protocol, cast
+from uuid import UUID, uuid4
+
+import httpx
+
+from ._generated.api.authentication import auth_signin
+from ._generated.api.database_queries import query_database_select
+from ._generated.api.locks import acquire_project_lock, release_project_lock
+from ._generated.api.storage_objects import (
+ download_storage_object,
+ upload_storage_object,
+)
+from ._generated.client import AuthenticatedClient
+from ._generated.models.auth_signin_body import AuthSigninBody
+from ._generated.models.database_select_request import DatabaseSelectRequest
+from ._generated.models.project_lock_lease_request import ProjectLockLeaseRequest
+from ._generated.models.upload_storage_object_files_body import (
+ UploadStorageObjectFilesBody,
+)
+from ._generated.types import File
+from .errors import (
+ AuthenticationError,
+ ConflictError,
+ NotFoundError,
+ RateLimitedError,
+ ServerError,
+ TransportError,
+ ValidationError,
+ VolcanoError,
+)
+
+
+@dataclass(frozen=True, slots=True)
+class TransportResponse:
+ status_code: int
+ payload: Any
+ content: bytes
+ headers: Mapping[str, str]
+
+
+class Transport(Protocol):
+ def auth_signin(
+ self,
+ *,
+ authorization: str,
+ email: str,
+ password: str,
+ ) -> TransportResponse: ...
+
+ def query_database_select(
+ self,
+ *,
+ authorization: str,
+ database_name: str,
+ body: dict[str, Any],
+ ) -> TransportResponse: ...
+
+ def upload_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ data: bytes,
+ ) -> TransportResponse: ...
+
+ def download_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ ) -> TransportResponse: ...
+
+ def acquire_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ ttl: int,
+ token: str,
+ ) -> TransportResponse: ...
+
+ def release_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ token: str,
+ ) -> TransportResponse: ...
+
+
+def invoke(operation: Callable[..., Any], **kwargs: Any) -> Any:
+ try:
+ return operation(**kwargs)
+ except httpx.HTTPError as error:
+ raise TransportError(str(error) or "Volcano transport failed") from error
+
+
+def _header(headers: Mapping[str, str] | None, name: str) -> str | None:
+ if headers is None:
+ return None
+ for key, value in headers.items():
+ if key.lower() == name.lower():
+ return value
+ return None
+
+
+def response_payload(response: Any, expected_status: int) -> Any:
+ status = int(response.status_code)
+ if status != expected_status:
+ payload = response.payload if isinstance(response.payload, dict) else {}
+ message = str(payload.get("error") or payload.get("message") or "Volcano request failed")
+ code_value = payload.get("code")
+ code = str(code_value) if code_value is not None else None
+ retry_after = None
+ if status == 429:
+ retry_after_value = _header(response.headers, "Retry-After")
+ try:
+ retry_after = int(retry_after_value) if retry_after_value is not None else None
+ except ValueError:
+ retry_after = None
+ error_type: type[VolcanoError]
+ if status in (401, 403):
+ error_type = AuthenticationError
+ elif status in (400, 422):
+ error_type = ValidationError
+ elif status == 404:
+ error_type = NotFoundError
+ elif status == 409:
+ error_type = ConflictError
+ elif status == 429:
+ error_type = RateLimitedError
+ elif 500 <= status <= 599:
+ error_type = ServerError
+ else:
+ error_type = VolcanoError
+ raise error_type(
+ message,
+ status=status,
+ code=code,
+ retry_after=retry_after,
+ )
+ return response.payload
+
+
+class GeneratedTransport:
+ def __init__(
+ self,
+ *,
+ api_url: str,
+ timeout: float = 60.0,
+ httpx_transport: httpx.BaseTransport | None = None,
+ ) -> None:
+ self._api_url = api_url.rstrip("/")
+ self._timeout = timeout
+ self._httpx_transport = httpx_transport
+
+ def _client(self, authorization: str) -> AuthenticatedClient:
+ httpx_args: dict[str, Any] = {}
+ if self._httpx_transport is not None:
+ httpx_args["transport"] = self._httpx_transport
+ return AuthenticatedClient(
+ base_url=self._api_url,
+ token=authorization,
+ timeout=httpx.Timeout(self._timeout),
+ httpx_args=httpx_args,
+ )
+
+ @staticmethod
+ def _response(response: Any) -> TransportResponse:
+ parsed = response.parsed
+ if hasattr(parsed, "to_dict"):
+ payload = parsed.to_dict()
+ elif parsed is not None:
+ payload = parsed
+ else:
+ try:
+ payload = json.loads(response.content)
+ except (json.JSONDecodeError, UnicodeDecodeError):
+ payload = None
+ return TransportResponse(
+ status_code=int(response.status_code),
+ payload=payload,
+ content=response.content,
+ headers=dict(response.headers),
+ )
+
+ def auth_signin(
+ self,
+ *,
+ authorization: str,
+ email: str,
+ password: str,
+ ) -> TransportResponse:
+ with self._client(authorization) as client:
+ response = auth_signin.sync_detailed(
+ client=client,
+ body=AuthSigninBody(email=email, password=password),
+ )
+ return self._response(response)
+
+ def query_database_select(
+ self,
+ *,
+ authorization: str,
+ database_name: str,
+ body: dict[str, Any],
+ ) -> TransportResponse:
+ with self._client(authorization) as client:
+ response = query_database_select.sync_detailed(
+ database_name,
+ client=client,
+ body=DatabaseSelectRequest.from_dict(body),
+ )
+ return self._response(response)
+
+ def upload_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ data: bytes,
+ ) -> TransportResponse:
+ file_name = PurePosixPath(path).name or "file"
+ body = UploadStorageObjectFilesBody(
+ file=File(
+ payload=BytesIO(data),
+ file_name=file_name,
+ mime_type="application/octet-stream",
+ )
+ )
+ with self._client(authorization) as client:
+ response = upload_storage_object.sync_detailed(
+ bucket_name,
+ path,
+ client=client,
+ body=body,
+ )
+ return self._response(response)
+
+ def download_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ ) -> TransportResponse:
+ with self._client(authorization) as client:
+ response = download_storage_object.sync_detailed(
+ bucket_name,
+ path,
+ client=client,
+ )
+ return self._response(response)
+
+ def acquire_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ ttl: int,
+ token: str,
+ ) -> TransportResponse:
+ with self._client(authorization) as client:
+ response = acquire_project_lock.sync_detailed(
+ key,
+ client=client,
+ body=ProjectLockLeaseRequest(ttl_seconds=ttl),
+ x_volcano_lock_token=cast(UUID, token),
+ x_volcano_request_id=cast(UUID, str(uuid4())),
+ )
+ return self._response(response)
+
+ def release_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ token: str,
+ ) -> TransportResponse:
+ with self._client(authorization) as client:
+ response = release_project_lock.sync_detailed(
+ key,
+ client=client,
+ x_volcano_lock_token=cast(UUID, token),
+ x_volcano_request_id=cast(UUID, str(uuid4())),
+ )
+ return self._response(response)
diff --git a/src/volcano_sdk/auth.py b/src/volcano_sdk/auth.py
new file mode 100644
index 00000000..821e1e29
--- /dev/null
+++ b/src/volcano_sdk/auth.py
@@ -0,0 +1,35 @@
+from __future__ import annotations
+
+from typing import Protocol
+
+from ._transport import Transport, invoke, response_payload
+from .models import Session
+
+
+class AuthContext(Protocol):
+ _transport: Transport
+
+ def _anon_token(self) -> str: ...
+
+ def _set_session(self, session: Session) -> None: ...
+
+
+class Auth:
+ def __init__(self, client: AuthContext) -> None:
+ self._client = client
+
+ def sign_in(self, *, email: str, password: str) -> Session:
+ response = invoke(
+ self._client._transport.auth_signin,
+ authorization=self._client._anon_token(),
+ email=email,
+ password=password,
+ )
+ payload = response_payload(response, 200)
+ session = Session(
+ access_token=payload["access_token"],
+ refresh_token=payload["refresh_token"],
+ user_id=payload["user"]["id"],
+ )
+ self._client._set_session(session)
+ return session
diff --git a/src/volcano_sdk/client.py b/src/volcano_sdk/client.py
index 1098614e..b47c6c16 100644
--- a/src/volcano_sdk/client.py
+++ b/src/volcano_sdk/client.py
@@ -1,2 +1,67 @@
+from __future__ import annotations
+
+from ._transport import GeneratedTransport, Transport
+from .auth import Auth
+from .database import Database
+from .locks import Locks
+from .models import Session
+from .realtime import CentrifugeFactory, Realtime
+from .storage import Storage
+
+
class VolcanoClient:
"""Volcano SDK entry point."""
+
+ def __init__(
+ self,
+ *,
+ anon_key: str,
+ api_url: str = "https://api.volcano.dev",
+ service_key: str | None = None,
+ timeout: float = 60.0,
+ _transport: Transport | None = None,
+ _realtime_client_factory: CentrifugeFactory | None = None,
+ ) -> None:
+ self._api_url = api_url.rstrip("/")
+ self._anon_key = anon_key
+ self._service_key = service_key
+ self._current_session: Session | None = None
+ self._transport: Transport = (
+ _transport
+ if _transport is not None
+ else GeneratedTransport(api_url=self._api_url, timeout=timeout)
+ )
+ self.auth = Auth(self)
+ self.storage = Storage(self)
+ self.locks = Locks(self)
+ if _realtime_client_factory is None:
+ self.realtime = Realtime(self, api_url=self._api_url)
+ else:
+ self.realtime = Realtime(
+ self,
+ api_url=self._api_url,
+ client_factory=_realtime_client_factory,
+ )
+
+ @property
+ def current_session(self) -> Session | None:
+ return self._current_session
+
+ def database(self, name: str) -> Database:
+ return Database(self, name)
+
+ def _anon_token(self) -> str:
+ return self._anon_key
+
+ def _session_token(self) -> str:
+ if self._current_session is None:
+ raise RuntimeError("No active session")
+ return self._current_session.access_token
+
+ def _service_token(self) -> str:
+ if self._service_key is None:
+ raise RuntimeError("No service key configured")
+ return self._service_key
+
+ def _set_session(self, session: Session) -> None:
+ self._current_session = session
diff --git a/src/volcano_sdk/database.py b/src/volcano_sdk/database.py
new file mode 100644
index 00000000..0db71c6c
--- /dev/null
+++ b/src/volcano_sdk/database.py
@@ -0,0 +1,52 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, replace
+from typing import Any, Protocol
+
+from ._transport import Transport, invoke, response_payload
+
+
+class DatabaseContext(Protocol):
+ _transport: Transport
+
+ def _session_token(self) -> str: ...
+
+
+@dataclass(frozen=True, slots=True)
+class QueryBuilder:
+ _client: DatabaseContext
+ _database_name: str
+ _table: str
+ _columns: tuple[str, ...] = ()
+ _filters: tuple[dict[str, Any], ...] = ()
+
+ def select(self, *columns: str) -> QueryBuilder:
+ return replace(self, _columns=columns)
+
+ def eq(self, column: str, value: Any) -> QueryBuilder:
+ condition = {"column": column, "operator": "eq", "value": value}
+ return replace(self, _filters=(*self._filters, condition))
+
+ def execute(self) -> list[dict[str, Any]]:
+ body: dict[str, Any] = {"table": self._table}
+ if self._columns and self._columns != ("*",):
+ body["select"] = list(self._columns)
+ if self._filters:
+ body["filters"] = list(self._filters)
+ response = invoke(
+ self._client._transport.query_database_select,
+ authorization=self._client._session_token(),
+ database_name=self._database_name,
+ body=body,
+ )
+ payload = response_payload(response, 200)
+ return list(payload["data"])
+
+
+@dataclass(frozen=True, slots=True)
+class Database:
+ _client: DatabaseContext
+ _name: str
+
+ def from_(self, table: str) -> QueryBuilder:
+ return QueryBuilder(self._client, self._name, table)
diff --git a/src/volcano_sdk/errors.py b/src/volcano_sdk/errors.py
new file mode 100644
index 00000000..e5aa819e
--- /dev/null
+++ b/src/volcano_sdk/errors.py
@@ -0,0 +1,44 @@
+from __future__ import annotations
+
+
+class VolcanoError(Exception):
+ def __init__(
+ self,
+ message: str,
+ *,
+ status: int | None = None,
+ code: str | None = None,
+ retry_after: int | None = None,
+ ) -> None:
+ super().__init__(message)
+ self.status = status
+ self.code = code
+ self.retry_after = retry_after
+
+
+class AuthenticationError(VolcanoError):
+ pass
+
+
+class ValidationError(VolcanoError):
+ pass
+
+
+class NotFoundError(VolcanoError):
+ pass
+
+
+class ConflictError(VolcanoError):
+ pass
+
+
+class RateLimitedError(VolcanoError):
+ pass
+
+
+class ServerError(VolcanoError):
+ pass
+
+
+class TransportError(VolcanoError):
+ pass
diff --git a/src/volcano_sdk/locks.py b/src/volcano_sdk/locks.py
new file mode 100644
index 00000000..44c2fb8c
--- /dev/null
+++ b/src/volcano_sdk/locks.py
@@ -0,0 +1,51 @@
+from __future__ import annotations
+
+from datetime import datetime
+from typing import Any, Protocol
+from uuid import uuid4
+
+from ._transport import Transport, invoke, response_payload
+from .models import LockLease
+
+
+class LocksContext(Protocol):
+ _transport: Transport
+
+ def _service_token(self) -> str: ...
+
+
+def _parse_datetime(value: Any) -> datetime | None:
+ if value is None:
+ return None
+ return datetime.fromisoformat(str(value))
+
+
+class Locks:
+ def __init__(self, client: LocksContext) -> None:
+ self._client = client
+
+ def acquire(self, key: str, *, ttl: int) -> LockLease:
+ token = str(uuid4())
+ response = invoke(
+ self._client._transport.acquire_project_lock,
+ authorization=self._client._service_token(),
+ key=key,
+ ttl=ttl,
+ token=token,
+ )
+ payload = response_payload(response, 201)
+ return LockLease(
+ key=key,
+ token=token,
+ expires_at=_parse_datetime(payload.get("expires_at")),
+ fencing_token=payload.get("fencing_token"),
+ )
+
+ def release(self, key: str, lease: LockLease) -> None:
+ response = invoke(
+ self._client._transport.release_project_lock,
+ authorization=self._client._service_token(),
+ key=key,
+ token=lease.token,
+ )
+ response_payload(response, 204)
diff --git a/src/volcano_sdk/models.py b/src/volcano_sdk/models.py
new file mode 100644
index 00000000..3bfd7462
--- /dev/null
+++ b/src/volcano_sdk/models.py
@@ -0,0 +1,19 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from datetime import datetime
+
+
+@dataclass(frozen=True, slots=True)
+class Session:
+ access_token: str
+ refresh_token: str
+ user_id: str
+
+
+@dataclass(frozen=True, slots=True)
+class LockLease:
+ key: str
+ token: str
+ expires_at: datetime | None
+ fencing_token: int | None
diff --git a/src/volcano_sdk/realtime.py b/src/volcano_sdk/realtime.py
new file mode 100644
index 00000000..57d53d3d
--- /dev/null
+++ b/src/volcano_sdk/realtime.py
@@ -0,0 +1,231 @@
+from __future__ import annotations
+
+import importlib
+import inspect
+from collections.abc import Awaitable, Callable
+from typing import Any, Protocol, cast
+from urllib.parse import quote, urlsplit, urlunsplit
+
+MessageCallback = Callable[[Any], Any]
+
+
+class RealtimeContext(Protocol):
+ def _anon_token(self) -> str: ...
+
+ def _session_token(self) -> str: ...
+
+
+class CentrifugeSubscription(Protocol):
+ async def subscribe(self) -> None: ...
+
+ async def publish(self, data: Any) -> Any: ...
+
+ async def unsubscribe(self) -> None: ...
+
+
+class CentrifugeConnection(Protocol):
+ async def connect(self) -> None: ...
+
+ async def disconnect(self) -> None: ...
+
+ def new_subscription(
+ self,
+ name: str,
+ *,
+ events: Any,
+ ) -> CentrifugeSubscription: ...
+
+
+class CentrifugeFactory(Protocol):
+ def __call__(
+ self,
+ address: str,
+ *,
+ token: str,
+ get_token: Callable[[], Awaitable[str]],
+ ) -> CentrifugeConnection: ...
+
+
+class CentrifugeConstructor(Protocol):
+ def __call__(
+ self,
+ address: str,
+ *,
+ token: str,
+ get_token: Callable[[], Awaitable[str]],
+ ) -> object: ...
+
+
+class Publication(Protocol):
+ data: Any
+
+
+class PublicationContext(Protocol):
+ pub: Publication
+
+
+def _centrifuge_client(
+ address: str,
+ *,
+ token: str,
+ get_token: Callable[[], Awaitable[str]],
+) -> CentrifugeConnection:
+ module = importlib.import_module("centrifuge")
+ constructor = cast(CentrifugeConstructor, module.Client)
+ return cast(
+ CentrifugeConnection,
+ constructor(address, token=token, get_token=get_token),
+ )
+
+
+class _ProjectAwareSubscriptions(dict[str, Any]):
+ def get(self, key: str, default: Any = None) -> Any:
+ subscription = super().get(key)
+ if subscription is not None:
+ return subscription
+ for channel, candidate in self.items():
+ if key.endswith(f":{channel}"):
+ return candidate
+ return default
+
+
+class _VolcanoCentrifugeConnection:
+ def __init__(self, connection: CentrifugeConnection) -> None:
+ self._connection = connection
+ state = vars(connection)
+ subscriptions = state.get("_subs")
+ if not isinstance(subscriptions, dict):
+ raise TypeError("centrifuge client subscription registry is unavailable")
+ state["_subs"] = _ProjectAwareSubscriptions(subscriptions)
+
+ async def connect(self) -> None:
+ await self._connection.connect()
+
+ async def disconnect(self) -> None:
+ await self._connection.disconnect()
+
+ def new_subscription(
+ self,
+ name: str,
+ *,
+ events: Any,
+ ) -> CentrifugeSubscription:
+ return self._connection.new_subscription(name, events=events)
+
+
+class _ChannelEvents:
+ def __init__(self, channel: Channel) -> None:
+ self._channel = channel
+
+ async def on_publication(self, ctx: PublicationContext) -> None:
+ await self._channel._emit(ctx.pub.data)
+
+ async def on_subscribing(self, ctx: Any) -> None:
+ del ctx
+
+ async def on_subscribed(self, ctx: Any) -> None:
+ del ctx
+
+ async def on_unsubscribed(self, ctx: Any) -> None:
+ del ctx
+
+ async def on_join(self, ctx: Any) -> None:
+ del ctx
+
+ async def on_leave(self, ctx: Any) -> None:
+ del ctx
+
+ async def on_error(self, ctx: Any) -> None:
+ del ctx
+
+
+class Channel:
+ def __init__(self, realtime: Realtime, name: str) -> None:
+ self._realtime = realtime
+ self._name = name
+ self._message_callbacks: list[MessageCallback] = []
+ self._subscription: CentrifugeSubscription | None = None
+
+ def on(self, event: str, callback: MessageCallback) -> Channel:
+ if event != "message":
+ raise ValueError(f"unsupported realtime event: {event}")
+ self._message_callbacks.append(callback)
+ return self
+
+ async def subscribe(self) -> None:
+ connection = await self._realtime._connect()
+ if self._subscription is None:
+ self._subscription = connection.new_subscription(
+ self._name,
+ events=_ChannelEvents(self),
+ )
+ await self._subscription.subscribe()
+
+ async def send(self, data: Any) -> None:
+ if self._subscription is None:
+ raise RuntimeError("Channel must be subscribed before sending")
+ await self._subscription.publish(data)
+
+ async def unsubscribe(self) -> None:
+ if self._subscription is None:
+ return
+ await self._subscription.unsubscribe()
+
+ async def _emit(self, data: Any) -> None:
+ for callback in tuple(self._message_callbacks):
+ result = callback(data)
+ if inspect.isawaitable(result):
+ await result
+
+ def _reset(self) -> None:
+ self._subscription = None
+
+
+class Realtime:
+ def __init__(
+ self,
+ client: RealtimeContext,
+ *,
+ api_url: str,
+ client_factory: CentrifugeFactory = _centrifuge_client,
+ ) -> None:
+ self._client_context = client
+ self._api_url = api_url
+ self._client_factory = client_factory
+ self._connection: CentrifugeConnection | None = None
+ self._channels: dict[str, Channel] = {}
+
+ def channel(self, name: str) -> Channel:
+ wire_name = f"broadcast:{name}"
+ if wire_name not in self._channels:
+ self._channels[wire_name] = Channel(self, wire_name)
+ return self._channels[wire_name]
+
+ async def _token(self) -> str:
+ return self._client_context._session_token()
+
+ def _address(self) -> str:
+ parsed = urlsplit(self._api_url)
+ scheme = "wss" if parsed.scheme == "https" else "ws"
+ query = f"apikey={quote(self._client_context._anon_token(), safe='')}"
+ return urlunsplit((scheme, parsed.netloc, "/realtime/v1/websocket", query, ""))
+
+ async def _connect(self) -> CentrifugeConnection:
+ if self._connection is None:
+ self._connection = _VolcanoCentrifugeConnection(
+ self._client_factory(
+ self._address(),
+ token=self._client_context._session_token(),
+ get_token=self._token,
+ )
+ )
+ await self._connection.connect()
+ return self._connection
+
+ async def disconnect(self) -> None:
+ if self._connection is None:
+ return
+ await self._connection.disconnect()
+ self._connection = None
+ for channel in self._channels.values():
+ channel._reset()
diff --git a/src/volcano_sdk/storage.py b/src/volcano_sdk/storage.py
new file mode 100644
index 00000000..84817d6a
--- /dev/null
+++ b/src/volcano_sdk/storage.py
@@ -0,0 +1,47 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import Any, Protocol
+
+from ._transport import Transport, invoke, response_payload
+
+
+class StorageContext(Protocol):
+ _transport: Transport
+
+ def _session_token(self) -> str: ...
+
+
+@dataclass(frozen=True, slots=True)
+class StorageBucket:
+ _client: StorageContext
+ _name: str
+
+ def upload(self, path: str, data: bytes) -> dict[str, Any]:
+ response = invoke(
+ self._client._transport.upload_storage_object,
+ authorization=self._client._session_token(),
+ bucket_name=self._name,
+ path=path,
+ data=data,
+ )
+ payload = response_payload(response, 201)
+ return dict(payload)
+
+ def download(self, path: str) -> bytes:
+ response = invoke(
+ self._client._transport.download_storage_object,
+ authorization=self._client._session_token(),
+ bucket_name=self._name,
+ path=path,
+ )
+ response_payload(response, 200)
+ return bytes(response.content)
+
+
+class Storage:
+ def __init__(self, client: StorageContext) -> None:
+ self._client = client
+
+ def from_(self, bucket: str) -> StorageBucket:
+ return StorageBucket(self._client, bucket)
diff --git a/tests/fixtures/sdk-contract-dry-run.json b/tests/fixtures/sdk-contract-dry-run.json
new file mode 100644
index 00000000..5e59774e
--- /dev/null
+++ b/tests/fixtures/sdk-contract-dry-run.json
@@ -0,0 +1,19 @@
+{
+ "api_url": "http://127.0.0.1:8000",
+ "project_id": "dry-run-project",
+ "anon_key": "dry-run-anon-key",
+ "service_key": "dry-run-service-key",
+ "user_id": "dry-run-user",
+ "user_email": "dry-run@example.com",
+ "user_password": "dry-run-password",
+ "database_name": "dry_run_database",
+ "table_name": "dry_run_table",
+ "fixture_row": {
+ "slug": "dry-run",
+ "value": "dry-run"
+ },
+ "bucket_name": "dry-run-bucket",
+ "storage_path": "dry-run/payload.txt",
+ "realtime_channel": "dry-run-channel",
+ "lock_key": "dry-run-lock"
+}
diff --git a/tests/unit/test_contract_bindings.py b/tests/unit/test_contract_bindings.py
new file mode 100644
index 00000000..606b9533
--- /dev/null
+++ b/tests/unit/test_contract_bindings.py
@@ -0,0 +1,85 @@
+from __future__ import annotations
+
+import hashlib
+import importlib.util
+import os
+import sys
+from pathlib import Path
+
+import pytest
+from behave.step_registry import registry
+
+ROOT = Path(__file__).parents[2]
+FEATURE_SHA256 = {
+ "auth.feature": "8e1b399dfc5062b59aca5c74f4ef17dcfd9442047ba6f14d0af95a3f44eb152b",
+ "database.feature": "4685b29357a621068b25984ff0de29cd4c504eebe5cfb597f0b999e29878a668",
+ "locks.feature": "76fa31f9a7c203e33b367e5ca1467b2334e7c85c960de8d5cab8638920137411",
+ "realtime.feature": "e65862e27656cdd0afa8e552cb5a628d9831568e3299711e572ccd4f6b750696",
+ "storage.feature": "a40db75b59dbd975185a3755345111a32c1e2b216ee5f5dd958c33dd3ef31457",
+}
+
+
+def _load_module(name: str, path: Path):
+ features_path = str(ROOT / "features")
+ if features_path not in sys.path:
+ sys.path.insert(0, features_path)
+ spec = importlib.util.spec_from_file_location(name, path)
+ assert spec is not None and spec.loader is not None
+ module = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(module)
+ return module
+
+
+def test_contract_features_match_shared_source() -> None:
+ copied = ROOT / "features" / "contract"
+ assert {path.name for path in copied.glob("*.feature")} == FEATURE_SHA256.keys()
+ for name, expected in FEATURE_SHA256.items():
+ assert hashlib.sha256((copied / name).read_bytes()).hexdigest() == expected
+
+
+def test_every_contract_phrase_is_bound_verbatim() -> None:
+ registry.clear()
+ _load_module("contract_steps", ROOT / "features" / "steps" / "sdk_contract_steps.py")
+ bound = {
+ definition.string
+ for definitions in registry.steps.values()
+ for definition in definitions
+ }
+ assert bound == {
+ "a service-role client",
+ "an authenticated client",
+ "exactly the fixture row is returned",
+ "one client subscribes and the other publishes the contract message",
+ "the SDK operation succeeds",
+ "the client acquires and releases the contract lock",
+ "the client selects the contract table where \"slug\" equals the fixture slug",
+ "the client signs in with the contract user's credentials",
+ "the client uploads and downloads the contract object",
+ "the confirmed contract user",
+ "the current session belongs to the contract user",
+ "the downloaded bytes equal the uploaded bytes",
+ "the released lease is no longer held",
+ "the subscriber receives the contract message within 10 seconds",
+ "two authenticated realtime clients",
+ }
+
+
+def test_fixture_loader_requires_absolute_private_file(tmp_path: Path) -> None:
+ environment = _load_module("contract_environment", ROOT / "features" / "environment.py")
+ fixture = tmp_path / "fixture.json"
+ fixture.write_text("{}", encoding="utf-8")
+
+ fixture.chmod(0o644)
+ with pytest.raises(PermissionError, match="0600"):
+ environment.load_fixture(fixture)
+
+ fixture.chmod(0o600)
+ assert environment.load_fixture(fixture) == {}
+
+ previous = Path.cwd()
+ os.chdir(tmp_path)
+ try:
+ with pytest.raises(ValueError, match="absolute"):
+ environment.load_fixture(Path("fixture.json"))
+ finally:
+ os.chdir(previous)
diff --git a/tests/unit/test_errors.py b/tests/unit/test_errors.py
new file mode 100644
index 00000000..e0008834
--- /dev/null
+++ b/tests/unit/test_errors.py
@@ -0,0 +1,91 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import Any
+
+import httpx
+import pytest
+
+from volcano_sdk import VolcanoClient
+from volcano_sdk.errors import (
+ AuthenticationError,
+ ConflictError,
+ NotFoundError,
+ RateLimitedError,
+ ServerError,
+ TransportError,
+ ValidationError,
+ VolcanoError,
+)
+
+
+@dataclass(frozen=True)
+class ErrorResponse:
+ status_code: int
+ payload: dict[str, Any]
+ content: bytes = b""
+ headers: dict[str, str] | None = None
+
+
+class ErrorTransport:
+ def __init__(self, failure: ErrorResponse | Exception) -> None:
+ self.failure = failure
+
+ def auth_signin(self, **kwargs: Any) -> ErrorResponse:
+ del kwargs
+ if isinstance(self.failure, Exception):
+ raise self.failure
+ return self.failure
+
+
+@pytest.mark.parametrize(
+ ("status", "expected"),
+ [
+ (400, ValidationError),
+ (401, AuthenticationError),
+ (403, AuthenticationError),
+ (404, NotFoundError),
+ (409, ConflictError),
+ (429, RateLimitedError),
+ (500, ServerError),
+ (503, ServerError),
+ ],
+)
+def test_http_failures_map_to_stable_error_categories(
+ status: int,
+ expected: type[VolcanoError],
+) -> None:
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=ErrorTransport(
+ ErrorResponse(
+ status,
+ {"error": "contract failure", "code": "contract_code"},
+ headers={"Retry-After": "17"},
+ )
+ ),
+ )
+
+ with pytest.raises(expected) as caught:
+ client.auth.sign_in(email="user@example.com", password="wrong")
+
+ assert str(caught.value) == "contract failure"
+ assert caught.value.status == status
+ assert caught.value.code == "contract_code"
+ assert caught.value.retry_after == (17 if status == 429 else None)
+
+
+def test_network_failure_maps_to_transport_error() -> None:
+ request = httpx.Request("POST", "https://api.test.volcano.dev/auth/signin")
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=ErrorTransport(httpx.ConnectError("connection failed", request=request)),
+ )
+
+ with pytest.raises(TransportError) as caught:
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ assert caught.value.status is None
+ assert caught.value.code is None
+ assert caught.value.retry_after is None
+ assert isinstance(caught.value.__cause__, httpx.ConnectError)
diff --git a/tests/unit/test_facade.py b/tests/unit/test_facade.py
new file mode 100644
index 00000000..3b70e52c
--- /dev/null
+++ b/tests/unit/test_facade.py
@@ -0,0 +1,134 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from datetime import UTC, datetime
+from typing import Any
+
+from volcano_sdk import LockLease, Session, VolcanoClient
+
+
+@dataclass(frozen=True)
+class FakeResponse:
+ status_code: int
+ payload: Any = None
+ content: bytes = b""
+ headers: dict[str, str] | None = None
+
+
+class FakeTransport:
+ def __init__(self) -> None:
+ self.calls: list[tuple[str, dict[str, Any]]] = []
+
+ def auth_signin(self, **kwargs: Any) -> FakeResponse:
+ self.calls.append(("authSignin", kwargs))
+ return FakeResponse(
+ 200,
+ {
+ "access_token": "access-token",
+ "refresh_token": "refresh-token",
+ "user": {"id": "user-123"},
+ },
+ )
+
+ def query_database_select(self, **kwargs: Any) -> FakeResponse:
+ self.calls.append(("queryDatabaseSelect", kwargs))
+ return FakeResponse(200, {"data": [{"slug": "a"}], "count": 1})
+
+ def upload_storage_object(self, **kwargs: Any) -> FakeResponse:
+ self.calls.append(("uploadStorageObject", kwargs))
+ return FakeResponse(201, {"name": "a.txt", "size": 5})
+
+ def download_storage_object(self, **kwargs: Any) -> FakeResponse:
+ self.calls.append(("downloadStorageObject", kwargs))
+ return FakeResponse(200, content=b"hello")
+
+ def acquire_project_lock(self, **kwargs: Any) -> FakeResponse:
+ self.calls.append(("acquireProjectLock", kwargs))
+ return FakeResponse(
+ 201,
+ {"expires_at": "2026-08-26T12:00:30Z", "fencing_token": 7},
+ )
+
+ def release_project_lock(self, **kwargs: Any) -> FakeResponse:
+ self.calls.append(("releaseProjectLock", kwargs))
+ return FakeResponse(204)
+
+
+def test_public_facade_delegates_to_the_six_contract_operations() -> None:
+ transport = FakeTransport()
+ client = VolcanoClient(
+ api_url="https://api.test.volcano.dev",
+ anon_key="anon-key",
+ service_key="service-key",
+ _transport=transport,
+ )
+
+ session = client.auth.sign_in(email="user@example.com", password="secret")
+ rows = (
+ client.database("main")
+ .from_("items")
+ .select("*")
+ .eq("slug", "a")
+ .execute()
+ )
+ uploaded = client.storage.from_("assets").upload("a.txt", b"hello")
+ downloaded = client.storage.from_("assets").download("a.txt")
+ lease = client.locks.acquire("build", ttl=30)
+ released = client.locks.release("build", lease)
+
+ assert session == Session(
+ access_token="access-token",
+ refresh_token="refresh-token",
+ user_id="user-123",
+ )
+ assert client.current_session is session
+ assert rows == [{"slug": "a"}]
+ assert uploaded == {"name": "a.txt", "size": 5}
+ assert downloaded == b"hello"
+ assert lease == LockLease(
+ key="build",
+ token=lease.token,
+ expires_at=datetime(2026, 8, 26, 12, 0, 30, tzinfo=UTC),
+ fencing_token=7,
+ )
+ assert released is None
+
+ assert [name for name, _ in transport.calls] == [
+ "authSignin",
+ "queryDatabaseSelect",
+ "uploadStorageObject",
+ "downloadStorageObject",
+ "acquireProjectLock",
+ "releaseProjectLock",
+ ]
+ assert transport.calls[0][1] == {
+ "authorization": "anon-key",
+ "email": "user@example.com",
+ "password": "secret",
+ }
+ assert transport.calls[1][1] == {
+ "authorization": "access-token",
+ "database_name": "main",
+ "body": {
+ "table": "items",
+ "filters": [{"column": "slug", "operator": "eq", "value": "a"}],
+ },
+ }
+ assert transport.calls[2][1] == {
+ "authorization": "access-token",
+ "bucket_name": "assets",
+ "path": "a.txt",
+ "data": b"hello",
+ }
+ assert transport.calls[3][1] == {
+ "authorization": "access-token",
+ "bucket_name": "assets",
+ "path": "a.txt",
+ }
+ assert transport.calls[4][1]["authorization"] == "service-key"
+ assert transport.calls[4][1]["key"] == "build"
+ assert transport.calls[4][1]["ttl"] == 30
+ assert transport.calls[4][1]["token"] == lease.token
+ assert transport.calls[5][1]["authorization"] == "service-key"
+ assert transport.calls[5][1]["key"] == "build"
+ assert transport.calls[5][1]["token"] == lease.token
diff --git a/tests/unit/test_generated_transport.py b/tests/unit/test_generated_transport.py
new file mode 100644
index 00000000..5e6ebfe6
--- /dev/null
+++ b/tests/unit/test_generated_transport.py
@@ -0,0 +1,147 @@
+from __future__ import annotations
+
+import json
+
+import httpx
+
+from volcano_sdk._transport import GeneratedTransport
+
+
+def test_generated_transport_calls_the_six_openapi_operations() -> None:
+ requests: list[httpx.Request] = []
+
+ def handle(request: httpx.Request) -> httpx.Response:
+ requests.append(request)
+ path = request.url.path
+ if path == "/auth/signin":
+ return httpx.Response(
+ 200,
+ json={
+ "access_token": "access-token",
+ "refresh_token": "refresh-token",
+ "user": {
+ "id": "00000000-0000-4000-8000-000000000010",
+ "email": "user@example.com",
+ "status": "active",
+ "email_confirmed": True,
+ "created_at": "2026-08-26T12:00:00Z",
+ "updated_at": "2026-08-26T12:00:00Z",
+ },
+ "expires_in": 3600,
+ "token_type": "bearer",
+ },
+ )
+ if path == "/databases/main/query/select":
+ return httpx.Response(200, json={"data": [{"slug": "a"}], "count": 1})
+ if request.method == "POST" and path == "/storage/assets/a.txt":
+ return httpx.Response(
+ 201,
+ json={
+ "id": "00000000-0000-4000-8000-000000000020",
+ "bucket_id": "00000000-0000-4000-8000-000000000030",
+ "name": "a.txt",
+ "is_public": False,
+ "size": 5,
+ "mime_type": "application/octet-stream",
+ "metadata": {},
+ "owner_id": "00000000-0000-4000-8000-000000000010",
+ "created_at": "2026-08-26T12:00:00Z",
+ "updated_at": "2026-08-26T12:00:00Z",
+ },
+ )
+ if request.method == "GET" and path == "/storage/assets/a.txt":
+ return httpx.Response(200, content=b"hello")
+ if request.method == "POST" and path == "/locks/build/lease":
+ return httpx.Response(
+ 201,
+ json={
+ "key": "build",
+ "expires_at": "2026-08-26T12:00:30Z",
+ "fencing_token": 7,
+ },
+ )
+ if request.method == "DELETE" and path == "/locks/build/lease":
+ return httpx.Response(204)
+ raise AssertionError(f"unexpected request: {request.method} {path}")
+
+ transport = GeneratedTransport(
+ api_url="https://api.test.volcano.dev",
+ httpx_transport=httpx.MockTransport(handle),
+ )
+
+ auth = transport.auth_signin(
+ authorization="anon-key",
+ email="user@example.com",
+ password="secret",
+ )
+ query = transport.query_database_select(
+ authorization="access-token",
+ database_name="main",
+ body={
+ "table": "items",
+ "select": ["*"],
+ "filters": [{"column": "slug", "operator": "eq", "value": "a"}],
+ },
+ )
+ upload = transport.upload_storage_object(
+ authorization="access-token",
+ bucket_name="assets",
+ path="a.txt",
+ data=b"hello",
+ )
+ download = transport.download_storage_object(
+ authorization="access-token",
+ bucket_name="assets",
+ path="a.txt",
+ )
+ acquire = transport.acquire_project_lock(
+ authorization="service-key",
+ key="build",
+ ttl=30,
+ token="00000000-0000-4000-8000-000000000001",
+ )
+ release = transport.release_project_lock(
+ authorization="service-key",
+ key="build",
+ token="00000000-0000-4000-8000-000000000001",
+ )
+
+ assert auth.payload["user"]["id"] == "00000000-0000-4000-8000-000000000010"
+ assert query.payload == {"data": [{"slug": "a"}], "count": 1}
+ assert upload.payload["name"] == "a.txt"
+ assert download.content == b"hello"
+ assert acquire.payload["fencing_token"] == 7
+ assert release.status_code == 204
+ assert [request.method for request in requests] == [
+ "POST",
+ "POST",
+ "POST",
+ "GET",
+ "POST",
+ "DELETE",
+ ]
+ assert [request.headers["authorization"] for request in requests] == [
+ "Bearer anon-key",
+ "Bearer access-token",
+ "Bearer access-token",
+ "Bearer access-token",
+ "Bearer service-key",
+ "Bearer service-key",
+ ]
+ assert json.loads(requests[0].content) == {
+ "email": "user@example.com",
+ "password": "secret",
+ }
+ assert json.loads(requests[1].content) == {
+ "table": "items",
+ "select": ["*"],
+ "filters": [{"column": "slug", "operator": "eq", "value": "a"}],
+ }
+ assert b"hello" in requests[2].content
+ assert json.loads(requests[4].content) == {"ttl_seconds": 30}
+ assert requests[4].headers["x-volcano-lock-token"] == (
+ "00000000-0000-4000-8000-000000000001"
+ )
+ assert requests[5].headers["x-volcano-lock-token"] == (
+ "00000000-0000-4000-8000-000000000001"
+ )
diff --git a/tests/unit/test_generation.py b/tests/unit/test_generation.py
new file mode 100644
index 00000000..7fa65cc3
--- /dev/null
+++ b/tests/unit/test_generation.py
@@ -0,0 +1,59 @@
+import os
+from pathlib import Path
+from runpy import run_path
+
+ROOT = Path(__file__).resolve().parents[2]
+
+def test_generate_emits_all_six_contract_operations(tmp_path: Path) -> None:
+ script = run_path(str(ROOT / "scripts" / "generate_openapi.py"))
+ generate = script["generate"]
+ output = tmp_path / "_generated"
+
+ generate(output)
+
+ assert {path.name for path in (output / "api").rglob("*.py")} >= {
+ "auth_signin.py",
+ "query_database_select.py",
+ "upload_storage_object.py",
+ "download_storage_object.py",
+ "acquire_project_lock.py",
+ "release_project_lock.py",
+ }
+
+
+def test_generated_comparison_reads_file_bytes(
+ monkeypatch: object,
+ tmp_path: Path,
+) -> None:
+ monkeypatch.syspath_prepend(str(ROOT / "scripts"))
+ script = run_path(str(ROOT / "scripts" / "check_openapi.py"))
+ compared_files = script["compared_files"]
+ expected = tmp_path / "expected"
+ actual = tmp_path / "actual"
+ expected.mkdir()
+ actual.mkdir()
+ (expected / "client.py").write_text("first\n", encoding="utf-8")
+ (actual / "client.py").write_text("other\n", encoding="utf-8")
+ timestamp = 1_800_000_000
+ os.utime(expected / "client.py", (timestamp, timestamp))
+ os.utime(actual / "client.py", (timestamp, timestamp))
+
+ missing, extra, changed = compared_files(expected, actual)
+
+ assert missing == []
+ assert extra == []
+ assert changed == ["client.py"]
+
+
+def test_generated_comparison_ignores_runtime_bytecode(tmp_path: Path) -> None:
+ script = run_path(str(ROOT / "scripts" / "check_openapi.py"))
+ compared_files = script["compared_files"]
+ expected = tmp_path / "expected"
+ actual = tmp_path / "actual"
+ (expected / "__pycache__").mkdir(parents=True)
+ actual.mkdir()
+ (expected / "client.py").write_text("source\n", encoding="utf-8")
+ (actual / "client.py").write_text("source\n", encoding="utf-8")
+ (expected / "__pycache__" / "client.pyc").write_bytes(b"runtime cache")
+
+ assert compared_files(expected, actual) == ([], [], [])
diff --git a/tests/unit/test_realtime.py b/tests/unit/test_realtime.py
new file mode 100644
index 00000000..fb5a3f51
--- /dev/null
+++ b/tests/unit/test_realtime.py
@@ -0,0 +1,136 @@
+from __future__ import annotations
+
+import asyncio
+from collections.abc import Awaitable, Callable
+from dataclasses import dataclass
+from types import SimpleNamespace
+from typing import Any
+
+from volcano_sdk import VolcanoClient
+
+
+@dataclass(frozen=True)
+class Response:
+ status_code: int
+ payload: Any
+ content: bytes = b""
+ headers: dict[str, str] | None = None
+
+
+class AuthTransport:
+ def __init__(self) -> None:
+ self.access_token = "access-1"
+
+ def auth_signin(self, **kwargs: Any) -> Response:
+ del kwargs
+ return Response(
+ 200,
+ {
+ "access_token": self.access_token,
+ "refresh_token": "refresh-token",
+ "user": {"id": "user-123"},
+ },
+ )
+
+
+class FakeSubscription:
+ def __init__(self, events: Any) -> None:
+ self.events = events
+ self.calls: list[tuple[str, Any]] = []
+
+ async def subscribe(self) -> None:
+ self.calls.append(("subscribe", None))
+
+ async def publish(self, data: Any) -> None:
+ self.calls.append(("publish", data))
+
+ async def unsubscribe(self) -> None:
+ self.calls.append(("unsubscribe", None))
+
+ async def emit(self, data: Any) -> None:
+ await self.events.on_publication(SimpleNamespace(pub=SimpleNamespace(data=data)))
+
+
+class FakeCentrifugeClient:
+ def __init__(self) -> None:
+ self.calls: list[str] = []
+ self.subscription: FakeSubscription | None = None
+ self._subs: dict[str, FakeSubscription] = {}
+
+ async def connect(self) -> None:
+ self.calls.append("connect")
+
+ async def disconnect(self) -> None:
+ self.calls.append("disconnect")
+
+ def new_subscription(self, name: str, *, events: Any) -> FakeSubscription:
+ self.calls.append(f"channel:{name}")
+ self.subscription = FakeSubscription(events)
+ self._subs[name] = self.subscription
+ return self.subscription
+
+ async def emit_wire_publication(self, name: str, data: Any) -> None:
+ subscription = self._subs.get(name)
+ if subscription is not None:
+ await subscription.emit(data)
+
+
+def test_realtime_wraps_official_client_without_exposing_it() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ factory_arguments: dict[str, Any] = {}
+
+ def factory(
+ address: str,
+ *,
+ token: str,
+ get_token: Callable[[], Awaitable[str]],
+ ) -> FakeCentrifugeClient:
+ factory_arguments.update(
+ address=address,
+ token=token,
+ get_token=get_token,
+ )
+ return official
+
+ client = VolcanoClient(
+ api_url="https://api.test.volcano.dev",
+ anon_key="anon key",
+ _transport=transport,
+ _realtime_client_factory=factory,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+ received: list[dict[str, str]] = []
+
+ async def scenario() -> None:
+ channel = client.realtime.channel("contract")
+ assert channel.on("message", received.append) is channel
+ assert await channel.subscribe() is None
+ assert official.subscription is not None
+ await official.emit_wire_publication(
+ "project-id:broadcast:contract",
+ {"event": "message", "value": "contract"},
+ )
+ assert received == [{"event": "message", "value": "contract"}]
+ assert await channel.send({"event": "message", "value": "contract"}) is None
+ assert await channel.unsubscribe() is None
+
+ transport.access_token = "access-2"
+ client.auth.sign_in(email="user@example.com", password="secret")
+ assert await factory_arguments["get_token"]() == "access-2"
+ assert await client.realtime.disconnect() is None
+
+ asyncio.run(scenario())
+
+ assert factory_arguments["address"] == (
+ "wss://api.test.volcano.dev/realtime/v1/websocket?apikey=anon%20key"
+ )
+ assert factory_arguments["token"] == "access-1"
+ assert official.calls == ["connect", "channel:broadcast:contract", "disconnect"]
+ assert official.subscription is not None
+ assert official.subscription.calls == [
+ ("subscribe", None),
+ ("publish", {"event": "message", "value": "contract"}),
+ ("unsubscribe", None),
+ ]
+ assert received == [{"event": "message", "value": "contract"}]
diff --git a/tests/unit/test_state.py b/tests/unit/test_state.py
new file mode 100644
index 00000000..5e4f12ef
--- /dev/null
+++ b/tests/unit/test_state.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import Any
+
+from volcano_sdk import VolcanoClient
+
+
+@dataclass(frozen=True)
+class Response:
+ status_code: int
+ payload: Any = None
+ content: bytes = b""
+ headers: dict[str, str] | None = None
+
+
+class StateTransport:
+ def __init__(self) -> None:
+ self.next_access_token = "access-1"
+ self.query_calls: list[dict[str, Any]] = []
+ self.authorizations: list[tuple[str, str]] = []
+
+ def auth_signin(self, **kwargs: Any) -> Response:
+ self.authorizations.append(("auth", kwargs["authorization"]))
+ return Response(
+ 200,
+ {
+ "access_token": self.next_access_token,
+ "refresh_token": f"refresh-{self.next_access_token}",
+ "user": {"id": "user-123"},
+ },
+ )
+
+ def query_database_select(self, **kwargs: Any) -> Response:
+ self.authorizations.append(("query", kwargs["authorization"]))
+ self.query_calls.append(kwargs["body"])
+ return Response(200, {"data": [kwargs["body"]], "count": 1})
+
+ def upload_storage_object(self, **kwargs: Any) -> Response:
+ self.authorizations.append(("upload", kwargs["authorization"]))
+ return Response(201, {"name": kwargs["path"]})
+
+ def download_storage_object(self, **kwargs: Any) -> Response:
+ self.authorizations.append(("download", kwargs["authorization"]))
+ return Response(200, content=b"bytes")
+
+ def acquire_project_lock(self, **kwargs: Any) -> Response:
+ self.authorizations.append(("acquire", kwargs["authorization"]))
+ return Response(201, {"expires_at": None, "fencing_token": 1})
+
+ def release_project_lock(self, **kwargs: Any) -> Response:
+ self.authorizations.append(("release", kwargs["authorization"]))
+ return Response(204)
+
+
+def test_query_builder_chains_are_immutable() -> None:
+ transport = StateTransport()
+ client = VolcanoClient(anon_key="anon", _transport=transport)
+ client.auth.sign_in(email="user@example.com", password="secret")
+ base = client.database("main").from_("items")
+ selected = base.select("*")
+ first = selected.eq("slug", "a")
+ second = selected.eq("slug", "b")
+
+ first.execute()
+ second.execute()
+
+ assert transport.query_calls == [
+ {
+ "table": "items",
+ "filters": [{"column": "slug", "operator": "eq", "value": "a"}],
+ },
+ {
+ "table": "items",
+ "filters": [{"column": "slug", "operator": "eq", "value": "b"}],
+ },
+ ]
+
+
+def test_each_request_reads_the_current_credentials() -> None:
+ transport = StateTransport()
+ client = VolcanoClient(
+ anon_key="anon-1",
+ service_key="service-1",
+ _transport=transport,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+ query = client.database("main").from_("items").select("*")
+ bucket = client.storage.from_("assets")
+
+ transport.next_access_token = "access-2"
+ client._anon_key = "anon-2"
+ client.auth.sign_in(email="user@example.com", password="secret")
+ query.execute()
+ bucket.upload("a.txt", b"bytes")
+ bucket.download("a.txt")
+ lease = client.locks.acquire("build", ttl=30)
+ client._service_key = "service-2"
+ client.locks.release("build", lease)
+
+ assert transport.authorizations == [
+ ("auth", "anon-1"),
+ ("auth", "anon-2"),
+ ("query", "access-2"),
+ ("upload", "access-2"),
+ ("download", "access-2"),
+ ("acquire", "service-1"),
+ ("release", "service-2"),
+ ]
diff --git a/uv.lock b/uv.lock
index 6016cc57..4199c535 100644
--- a/uv.lock
+++ b/uv.lock
@@ -6,6 +6,37 @@ resolution-markers = [
"python_full_version < '3.15'",
]
+[[package]]
+name = "annotated-doc"
+version = "0.0.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" },
+]
+
+[[package]]
+name = "annotated-types"
+version = "0.8.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" },
+]
+
+[[package]]
+name = "anyio"
+version = "4.14.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "idna" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" },
+]
+
[[package]]
name = "ast-serialize"
version = "0.8.0"
@@ -70,6 +101,68 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/25/6c/b400476d3ceba681ab929787edc9554f6d88fcc69435eb681b00fc0457a5/ast_serialize-0.8.0-cp39-abi3-win_arm64.whl", hash = "sha256:b2a5978662fd4db463dfb4b974d2b10ac6430b98f5333aabc7051909df3561d0", size = 1083655, upload-time = "2026-08-07T11:29:00.349Z" },
]
+[[package]]
+name = "attrs"
+version = "26.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" },
+]
+
+[[package]]
+name = "behave"
+version = "1.3.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama" },
+ { name = "cucumber-expressions" },
+ { name = "cucumber-tag-expressions" },
+ { name = "parse" },
+ { name = "parse-type" },
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/62/51/f37442fe648b3e35ecf69bee803fa6db3f74c5b46d6c882d0bc5654185a2/behave-1.3.3.tar.gz", hash = "sha256:2b8f4b64ed2ea756a5a2a73e23defc1c4631e9e724c499e46661778453ebaf51", size = 892639, upload-time = "2025-09-04T12:12:02.531Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/63/71/06f74ffed6d74525c5cd6677c97bd2df0b7649e47a249cf6a0c2038083b2/behave-1.3.3-py2.py3-none-any.whl", hash = "sha256:89bdb62af8fb9f147ce245736a5de69f025e5edfb66f1fbe16c5007493f842c0", size = 223594, upload-time = "2025-09-04T12:12:00.3Z" },
+]
+
+[[package]]
+name = "build"
+version = "1.5.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "os_name == 'nt'" },
+ { name = "packaging" },
+ { name = "pyproject-hooks" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/78/e0/df5e171f685f82f37b12e1f208064e24244911079d7b767447d1af7e0d70/build-1.5.0.tar.gz", hash = "sha256:302c22c3ba2a0fd5f3911918651341ebb3896176cbdec15bd421f80b1afc7647", size = 89796, upload-time = "2026-04-30T03:18:25.17Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl", hash = "sha256:13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f", size = 26018, upload-time = "2026-04-30T03:18:23.644Z" },
+]
+
+[[package]]
+name = "centrifuge-python"
+version = "0.6.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "protobuf" },
+ { name = "websockets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0f/1b/9903569c33ceb3a5a0c431264405003e7adfe828abf5fb597a639438af2c/centrifuge_python-0.6.0.tar.gz", hash = "sha256:8be7fcea0a6b95d46479f8c52c5f2a3c97dd11feb07e9f4e99730cafb52e80c9", size = 68022, upload-time = "2026-08-02T12:47:14.048Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/78/0966a25dd202aa936a916edf5be3eae21790bfa989aafca9a35c3c103b2f/centrifuge_python-0.6.0-py3-none-any.whl", hash = "sha256:18e5e9db30b0737727485454ae9b637d1cfcd93c27ca7bc257aad5623b3871da", size = 35639, upload-time = "2026-08-02T12:47:13.033Z" },
+]
+
+[[package]]
+name = "certifi"
+version = "2026.7.22"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55", size = 138112, upload-time = "2026-07-22T03:35:12.644Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z" },
+]
+
[[package]]
name = "colorama"
version = "0.4.6"
@@ -79,6 +172,70 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
]
+[[package]]
+name = "cucumber-expressions"
+version = "20.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/a3/001d7725688d5f8ae7d73d746457c9d11b851a4bad3a315dc7762144ec96/cucumber_expressions-20.1.0.tar.gz", hash = "sha256:0d216ec26e36c71b3e5643f2e72c41f9b266ef04eaa0c7e47a6e3b2caf523b1a", size = 13826, upload-time = "2026-08-05T20:16:52.542Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ea/b1/fba2393968001b2307facb76e0bc47be5c67185df752a8f5b61926d26760/cucumber_expressions-20.1.0-py3-none-any.whl", hash = "sha256:640782ebaef82313dc64e4684d0e5c5efbab0611b23f0cfad64f90c7041cf73d", size = 20230, upload-time = "2026-08-05T20:16:51.565Z" },
+]
+
+[[package]]
+name = "cucumber-tag-expressions"
+version = "11.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/50/e0/c2741558040293465d615a4f2555e9180c54a559119b96ff0251dda5fa90/cucumber_tag_expressions-11.0.1.tar.gz", hash = "sha256:f8304dd16e546517816e62ace6c486575023812f42e8a60526fcec1694016146", size = 8635, upload-time = "2026-08-05T20:33:20.775Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f8/2a/894aded5804c76cf148965721cb57fed0d923ddb2747a77c9147f20d58a9/cucumber_tag_expressions-11.0.1-py3-none-any.whl", hash = "sha256:8ee5433a3b1ad16ca607c905fa3bb6d85d57f087ba119b14ea5e82cd35ea98c5", size = 9757, upload-time = "2026-08-05T20:33:19.95Z" },
+]
+
+[[package]]
+name = "h11"
+version = "0.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
+]
+
+[[package]]
+name = "httpcore"
+version = "1.0.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "h11" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
+]
+
+[[package]]
+name = "httpx"
+version = "0.28.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "certifi" },
+ { name = "httpcore" },
+ { name = "idna" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
+]
+
+[[package]]
+name = "idna"
+version = "3.19"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/5f/f7/abb373e5757eaec4b922b92f97ec8d6d7e057cf06778247604fbc4e7c3f3/idna-3.19.tar.gz", hash = "sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15", size = 215237, upload-time = "2026-08-18T05:14:24.27Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/57/b0/0e52c878c53f245edd3a11020f20979b3f490f245af532c7cae3027754b5/idna-3.19-py3-none-any.whl", hash = "sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4", size = 68550, upload-time = "2026-08-18T05:14:22.343Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.3.0"
@@ -88,6 +245,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
]
+[[package]]
+name = "jinja2"
+version = "3.1.6"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markupsafe" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
+]
+
[[package]]
name = "librt"
version = "0.15.0"
@@ -204,6 +373,101 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/38/a6/800800bfed7b1fb10fc3f3d557785c3854e80d3f7a9800d784b176a1fc2d/librt-0.15.0-cp315-cp315t-win_arm64.whl", hash = "sha256:84d244b00604d17df3fc7736c327892d6bba66181254aa4087be807b6c342bdc", size = 110700, upload-time = "2026-08-07T10:49:15.499Z" },
]
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" },
+ { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" },
+ { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" },
+ { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" },
+ { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" },
+ { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" },
+ { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" },
+ { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" },
+ { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" },
+ { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" },
+ { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" },
+ { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" },
+ { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" },
+ { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" },
+ { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" },
+ { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" },
+ { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" },
+ { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" },
+ { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" },
+ { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" },
+ { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" },
+ { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" },
+ { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" },
+ { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" },
+ { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" },
+ { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" },
+ { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" },
+ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
[[package]]
name = "mypy"
version = "2.3.1"
@@ -273,6 +537,26 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
]
+[[package]]
+name = "openapi-python-client"
+version = "0.29.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "httpx" },
+ { name = "jinja2" },
+ { name = "pydantic" },
+ { name = "ruamel-yaml" },
+ { name = "ruff" },
+ { name = "shellingham" },
+ { name = "typer" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/63/f6/67dfe73b5073251b6e2aba3d67191819798dd33dd09fcb2d12242662a960/openapi_python_client-0.29.0.tar.gz", hash = "sha256:4ff439a63765aaef548e69c4eedd86dfad57891dc322709450af0c2c9a72a23e", size = 125697, upload-time = "2026-05-30T20:32:10.533Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fb/d1/7391a205622c40b8e9d1b79b892b4944d6e3637674b47a56196e2c96c5d1/openapi_python_client-0.29.0-py3-none-any.whl", hash = "sha256:1085864c1e0a42fb50e1f5eb84363b19de07ebfb8a3f82a146c8529b948b8f12", size = 182954, upload-time = "2026-05-30T20:32:09.037Z" },
+]
+
[[package]]
name = "packaging"
version = "26.3"
@@ -282,6 +566,28 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" },
]
+[[package]]
+name = "parse"
+version = "1.22.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a4/f2/0b504486c2a5564798607d3860e48ed19c6443d5e9cc3ec61cc6b8b4ef58/parse-1.22.1.tar.gz", hash = "sha256:d3a4740ec3da338e2b258b2d69741b731eadfddca59e24a14bc4ee5fce38c911", size = 36970, upload-time = "2026-05-26T03:44:52.624Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6f/c5/7c16e99869e1f422629092cfd23e3b58e461988c3f9c36fd3624bb4142e6/parse-1.22.1-py2.py3-none-any.whl", hash = "sha256:20f0925a46f06602485ac90d751764d0697fd8455aaa97489ba8953a4b66de32", size = 20925, upload-time = "2026-05-26T03:44:51.156Z" },
+]
+
+[[package]]
+name = "parse-type"
+version = "0.6.6"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "parse" },
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/19/ea/42ba6ce0abba04ab6e0b997dcb9b528a4661b62af1fe1b0d498120d5ea78/parse_type-0.6.6.tar.gz", hash = "sha256:513a3784104839770d690e04339a8b4d33439fcd5dd99f2e4580f9fc1097bfb2", size = 98012, upload-time = "2025-08-11T22:53:48.066Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/85/8d/eef3d8cdccc32abdd91b1286884c99b8c3a6d3b135affcc2a7a0f383bb32/parse_type-0.6.6-py2.py3-none-any.whl", hash = "sha256:3ca79bbe71e170dfccc8ec6c341edfd1c2a0fc1e5cfd18330f93af938de2348c", size = 27085, upload-time = "2025-08-11T22:53:46.396Z" },
+]
+
[[package]]
name = "pathspec"
version = "1.1.1"
@@ -300,6 +606,138 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
]
+[[package]]
+name = "protobuf"
+version = "7.36.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a7/e7/0553e21d25ca4d9f573135775348a372c3ec34a93a71d5f297c3bac38341/protobuf-7.36.0.tar.gz", hash = "sha256:e8e09cb0d794c6687926fa558a8a6e72aa10edb997d5ca61da0765f12a3e00ea", size = 510034, upload-time = "2026-08-20T16:34:01.071Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8f/ae/58e3ca96cb2e118cc546b677359b3c6659f79a140935c08dec94c7998585/protobuf-7.36.0-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:9103532dffd80c6fab7e50c65a31007680a06eb57537d437bb1b35812c138a37", size = 453256, upload-time = "2026-08-20T16:33:53.945Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/15/5162230af4912697f0fe406f6800f80760945babcff0e2c2fe6c84ef2d5d/protobuf-7.36.0-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:bf94a5917c71058262de683669bc0a797a7669d3de71f0b36d058e3194f47b44", size = 341436, upload-time = "2026-08-20T16:33:55.134Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/09/1670b2bfc9a45e807e520c3e9be36524db9ccc7dc05ea17af7681cabdc61/protobuf-7.36.0-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:3297e60abdff301e5f74393d87f6cc59dacab5f024a89548a6e8de1d26576b16", size = 354440, upload-time = "2026-08-20T16:33:56.077Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/f8/bd5804695ba400e423c33fd4d9f58c28d86633d5ba1945c36ff3967d98cb/protobuf-7.36.0-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:70f5ec8eb0da81a44360c0dc0beac99a0d78071d21956a7076bae8bd2051841b", size = 340439, upload-time = "2026-08-20T16:33:56.992Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/9f/acd02338235a3e7d03168c4303478347b7624fc8189ff4e7f0d2654bbe86/protobuf-7.36.0-cp310-abi3-win32.whl", hash = "sha256:7326fd717bdc419162a735938d89d4032332bcc3408804012b24ff3a37086071", size = 440216, upload-time = "2026-08-20T16:33:57.99Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/4e/12cb93270967a2affff5b3f720694700d4d87712a67afd05c8cb3f6fa52c/protobuf-7.36.0-cp310-abi3-win_amd64.whl", hash = "sha256:1781cc1de61249b750848029bca452c0a8b7e990080316b9bbc2518b2117b488", size = 453731, upload-time = "2026-08-20T16:33:58.951Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c3/629999e78d46c1115c11886d51c6bd68c17ce4a944f1ea3e153a91316a33/protobuf-7.36.0-py3-none-any.whl", hash = "sha256:53374d53fc29a67f7dbbf0ade47d7526a0f0137bf0f9c90e48d8a60790ef748c", size = 177024, upload-time = "2026-08-20T16:34:00.053Z" },
+]
+
+[[package]]
+name = "pydantic"
+version = "2.13.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-types" },
+ { name = "pydantic-core" },
+ { name = "typing-extensions" },
+ { name = "typing-inspection" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" },
+]
+
+[[package]]
+name = "pydantic-core"
+version = "2.46.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" },
+ { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" },
+ { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" },
+ { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" },
+ { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" },
+ { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" },
+ { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" },
+ { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" },
+ { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" },
+ { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" },
+ { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" },
+ { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" },
+ { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" },
+ { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" },
+ { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" },
+ { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" },
+ { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" },
+ { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" },
+ { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" },
+ { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" },
+ { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" },
+ { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" },
+ { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" },
+ { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" },
+ { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" },
+ { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" },
+ { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" },
+ { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" },
+ { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" },
+ { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" },
+ { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" },
+ { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" },
+ { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" },
+ { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" },
+ { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" },
+ { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" },
+ { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" },
+ { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" },
+ { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" },
+ { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" },
+ { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" },
+]
+
[[package]]
name = "pygments"
version = "2.21.0"
@@ -309,6 +747,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" },
]
+[[package]]
+name = "pyproject-hooks"
+version = "1.2.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" },
+]
+
[[package]]
name = "pytest"
version = "9.1.1"
@@ -325,6 +772,40 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
]
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruamel-yaml"
+version = "0.19.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c7/3b/ebda527b56beb90cb7652cb1c7e4f91f48649fbcd8d2eb2fb6e77cd3329b/ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993", size = 142709, upload-time = "2026-01-02T16:50:31.84Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b8/0c/51f6841f1d84f404f92463fc2b1ba0da357ca1e3db6b7fbda26956c3b82a/ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93", size = 118102, upload-time = "2026-01-02T16:50:29.201Z" },
+]
+
[[package]]
name = "ruff"
version = "0.16.4"
@@ -350,6 +831,48 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0e/fe/da8b9e1347696bb22120b77280ec5ce25d500ca5cb39d5ad6e5c18de19c1/ruff-0.16.4-py3-none-win_arm64.whl", hash = "sha256:a3a61621c9b6f6a89573e938a080e648f1695baa3f58570a3a707bc51ff65a21", size = 10451579, upload-time = "2026-08-20T17:43:57.135Z" },
]
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.26.8"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7c/f7/68adc395201b20b872d68e975386832e8005ffeacedd43a1d837a32815be/typer-0.26.8.tar.gz", hash = "sha256:c244a6bd558886fe3f8780efb6bdd28bb9aff005a94eedebaa5cb32926fe2f7e", size = 202097, upload-time = "2026-06-26T09:22:45.705Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/80/87/b9fd69c92c6102a066e1b86a35243f53e70bd4c709f2a26d9f4fee4f4dc0/typer-0.26.8-py3-none-any.whl", hash = "sha256:3512ca79ac5c11113414b36e80281b872884477722440691c89d1112e321a49c", size = 122564, upload-time = "2026-06-26T09:22:44.72Z" },
+]
+
+[[package]]
+name = "types-python-dateutil"
+version = "2.9.0.20260807"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c8/4e/b3fa538f9cb38dfece0d6ccf6d3d0d925bdedb144fb9c8129dfc007cd003/types_python_dateutil-2.9.0.20260807.tar.gz", hash = "sha256:e0b8a90d464c8684c66b7b8e4556d9074afdddcc56ca45323f0987134f9e7034", size = 17618, upload-time = "2026-08-07T04:17:13.491Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e4/5e/3715867caea2f4cea56ccb04c851cde23ed063449c3b004c7a047f20dd48/types_python_dateutil-2.9.0.20260807-py3-none-any.whl", hash = "sha256:54aa3707350ed7a9cc0776fd2f6739679d6967d11b40150985e81edcb86df4db", size = 18486, upload-time = "2026-08-07T04:17:12.504Z" },
+]
+
[[package]]
name = "typing-extensions"
version = "4.16.0"
@@ -359,23 +882,212 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
]
+[[package]]
+name = "typing-inspection"
+version = "0.4.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a3/26/b09b8010994eccc3c09092e6b34058f36a460eea2d4c3e8b910c695975a0/typing_inspection-0.4.4.tar.gz", hash = "sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47", size = 76928, upload-time = "2026-08-12T12:37:25.997Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/67/81/4add07e5172b7ac40d8ed5ff580409a7801a4fe26d529bdd915401dabfbe/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147", size = 14750, upload-time = "2026-08-12T12:37:24.648Z" },
+]
+
[[package]]
name = "volcano-sdk"
version = "0.1.0"
source = { editable = "." }
+dependencies = [
+ { name = "attrs" },
+ { name = "centrifuge-python" },
+ { name = "httpx" },
+ { name = "python-dateutil" },
+ { name = "typing-extensions" },
+]
[package.dev-dependencies]
dev = [
+ { name = "behave" },
+ { name = "build" },
{ name = "mypy" },
+ { name = "openapi-python-client" },
{ name = "pytest" },
{ name = "ruff" },
+ { name = "types-python-dateutil" },
]
[package.metadata]
+requires-dist = [
+ { name = "attrs", specifier = ">=26.1.0" },
+ { name = "centrifuge-python", specifier = ">=0.6.0,<0.7.0" },
+ { name = "httpx", specifier = ">=0.28.1,<0.29.0" },
+ { name = "python-dateutil", specifier = ">=2.9.0.post0,<3.0.0" },
+ { name = "typing-extensions", specifier = ">=4.15.0" },
+]
[package.metadata.requires-dev]
dev = [
+ { name = "behave", specifier = ">=1.3.3,<2.0.0" },
+ { name = "build", specifier = ">=1.5.0,<2.0.0" },
{ name = "mypy", specifier = ">=1.18.0" },
+ { name = "openapi-python-client", specifier = "==0.29.0" },
{ name = "pytest", specifier = ">=8.3.0" },
{ name = "ruff", specifier = ">=0.9.0" },
+ { name = "types-python-dateutil", specifier = ">=2.9.0.20250822" },
+]
+
+[[package]]
+name = "websockets"
+version = "17.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/18/72/fba934cb3dff7a85d811820efffcd141ddd52b5a2a01637f64551373ff4d/websockets-17.1.tar.gz", hash = "sha256:acfea4c20bf54384883ea33b1240fc1db4f52e190823a4e2b334bc3e8bfca96a", size = 187520, upload-time = "2026-08-26T17:25:33.063Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7d/ad/66a74d42fb537bd44056483eae6cbb7ebb10b742c300a0bf8cee427556d4/websockets-17.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:88b882764ef65147a7a5ae13168dedbe225a04e2ff4858fe543f2c402f093e9c", size = 216984, upload-time = "2026-08-26T14:55:20.747Z" },
+ { url = "https://files.pythonhosted.org/packages/70/1b/344ab22cea729e872f759b926441f7b822ab6cd106db527736afc066927f/websockets-17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98a5b2589a56a4b4f098b0a958099a4356ab904a7844f1da3841efca469af7e9", size = 214667, upload-time = "2026-08-26T14:55:22.298Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/42/bace574b6ae80e1a8d6935b8c5f03fb67236233ec572e976fe826ff719cf/websockets-17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:020e271205f8ab3406d7a59cd00de6dec722315924411c421bd00642f18bad86", size = 214944, upload-time = "2026-08-26T14:55:23.618Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/87/08e35ca4a0ffafb500a16ff461bf9561ad2b755362adb5d077d4dba9affc/websockets-17.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:65be6bda2b537fefa4b3a5ccd6ab386533ce39dd8fe62433ec90901fdc81752d", size = 224004, upload-time = "2026-08-26T14:55:24.748Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/9a/00ae2e147eaa086fe8bdddd36f57216ce72b9a9dfc0b17c717005ebdacaf/websockets-17.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0c84bdef916556cbe1d5a43b423398be4dd3cba6522b463e53d848578b920695", size = 224278, upload-time = "2026-08-26T14:55:26.016Z" },
+ { url = "https://files.pythonhosted.org/packages/98/e2/7aeb4e00defa68826f449392922a382ce7fdf542fe52190558dc1714e284/websockets-17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47a62d6045c6eaa0d8f97bc2fb68b8cf90077a0cbfd4e83d6f2d2145611ee134", size = 225511, upload-time = "2026-08-26T14:55:27.183Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/e4/655be3d93c3edbe1a51606073b5454ea6b1b32d87aa26253a6df952417b7/websockets-17.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34879e19bb0a3c44f9317679435aea5327fac993933a704cbf353bf1234b10c7", size = 228802, upload-time = "2026-08-26T14:55:28.431Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/33/98549a2afa9d68fe1b5a8e0a61cd461a43ea1ab7209bce675eea67c79190/websockets-17.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2d72879819f5145a342d0030c418702496c65a4b913ef81f5ae944dd91dd50f6", size = 226075, upload-time = "2026-08-26T14:55:29.695Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/6b/cbc27e014d6c292b9b2709cfd32781a2b61eb30cd4c9130e7c57e41a204a/websockets-17.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:84f25e099fdfe3b09f953d84698f729a1f7d1e99101b2787d7a28ed77b323750", size = 224846, upload-time = "2026-08-26T14:55:30.964Z" },
+ { url = "https://files.pythonhosted.org/packages/10/a6/e57925f7a423d90f24559e85bac21a7f0b44c0cf4a5c0babc0759ca54bab/websockets-17.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:469355ab1af100b9380f1afb09985019f4a4b94fa1dd0e9396db4361626d7ab8", size = 222136, upload-time = "2026-08-26T14:55:32.376Z" },
+ { url = "https://files.pythonhosted.org/packages/32/07/b9de0400addb542ba7c819022abc3afa46cd7e518068881bceadac69d995/websockets-17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:00679b7468b4c2b12b0757118174e8eabac56bb2f579a928a104d9554a56e098", size = 225000, upload-time = "2026-08-26T14:55:33.527Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/bb/af2828a1d7f2beb792af6ba56d7b02d56262070266b95d2af9ef391fbfb0/websockets-17.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a9fe648abd1d9b89aebfa30407bfdd08a0271ec5dc7d44a4c6ccd1ce22cf562a", size = 223592, upload-time = "2026-08-26T14:55:34.636Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/51/7379f254730c1dc7d8e4dd8d686868d8f7be55bdc94c6d3a44538840f639/websockets-17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f47aafd92aa28b941180e6da8a42b0f711851b14b81a5b6bb28dbbb1fa35152c", size = 224360, upload-time = "2026-08-26T14:55:35.777Z" },
+ { url = "https://files.pythonhosted.org/packages/88/c6/fcd91320dd71dda7046df9bc60f60c70ee15c052dee21e31ed6221dc8b5d/websockets-17.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c89406fa3dcd4aa8662c6406cc5c0de1790e9614d2c3aaf03ca53a8a8ccf3405", size = 225404, upload-time = "2026-08-26T14:55:36.85Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/b2/655a4f939388079f80f1b3f8a1b9d40783e70a376e7423988cc9a590a09f/websockets-17.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:b3b451fd2723ad3191a209afe6f3f4bc86c83e9a85bdc255353b91803ee6aa66", size = 222982, upload-time = "2026-08-26T14:55:38.006Z" },
+ { url = "https://files.pythonhosted.org/packages/87/75/37c84c4371c6aa668910d7841036c4397ea10554c07030603ccd5e44b02a/websockets-17.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:054c28db2dcec0e857e3b705d8c28012613e555b38c765d6a4f75340a4fc06a0", size = 224017, upload-time = "2026-08-26T14:55:39.39Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/20/8a9a94323bfcfe03bde3f9d98926bea4855856359702fe3ca0d07051ef5d/websockets-17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f8e822efd54137d8cc8310eb64635ab827a4a6c72ff08691f38aa624776d8ecb", size = 224252, upload-time = "2026-08-26T14:55:40.498Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/dd/aa66e6500188cd40306abeb92c9a738ca6dd7029d8d8532c538055ab5daf/websockets-17.1-cp311-cp311-win32.whl", hash = "sha256:dcb8d5f7edef7a399d322cf28d4c4e6f98dab64d301c8f50581a1080e5198142", size = 217484, upload-time = "2026-08-26T14:55:41.763Z" },
+ { url = "https://files.pythonhosted.org/packages/01/a2/cdf3b551f0b9177023afd3a45d3b431a0d4064951008c4321a8b42ac2288/websockets-17.1-cp311-cp311-win_amd64.whl", hash = "sha256:b1bc819c6db90e8f91a38250a1ab4c058261871aa52d2fe36382eddedf146dee", size = 217779, upload-time = "2026-08-26T14:55:42.942Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/13/51253dbed7d16a4bb87b05110ad3bf12165f410e915f6da1edd4186d8dc1/websockets-17.1-cp311-cp311-win_arm64.whl", hash = "sha256:edadce7a22052056fd4384543019856b34850363c9d387929f677ae01d79709c", size = 217710, upload-time = "2026-08-26T14:55:44.016Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/0d/098f23c4c858e5de9459ffc554fa07d5493fbcfca7f040b5800cf1cecc35/websockets-17.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:76dd004f59115087c7b700474cb18f01325e37250032e19396c08ae41448e4b3", size = 217015, upload-time = "2026-08-26T14:55:45.194Z" },
+ { url = "https://files.pythonhosted.org/packages/13/86/bc1317b1a4d8c4688e2a7e564b5e004dab44c2534d7ca05de6ae9a863fca/websockets-17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:581fa678ef46f4277cc8491312468e582f8ad609dbab907ba6096a08c6a0ff98", size = 214692, upload-time = "2026-08-26T14:55:46.366Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/e7/df821761772beaa48c211ee0e234930b35c1473778470773823f56d3911b/websockets-17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:87f0d5e77548b0c40c8464cdb6108792e7e53f487c6400028a4ec28a8afbe5ab", size = 214959, upload-time = "2026-08-26T14:55:47.885Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/92/c3fb72f11764812fc648bf3838d224972427b348e8b3989d9e0a9df87da3/websockets-17.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:882af300d2c6a092b93767d5de03c7bb56dfb06314140c8e872d3f48e09f7b74", size = 224278, upload-time = "2026-08-26T14:55:49.241Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/05/9f82d090c8d2d861604147ef6dfb938a90b039f9358d5193f1df62558593/websockets-17.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0c863507ada5805517ca6dff1c524dcd42942efe6304dacf06700878398d21a6", size = 224557, upload-time = "2026-08-26T14:55:50.348Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/50/5cbf677b865290fe36819ff00615826e7edc1df38786f770123ff39a933d/websockets-17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d41ef69d5416fbc1d98cf96c37be6192d10fd101c3e0f8b3ddc36e09432b3c08", size = 225791, upload-time = "2026-08-26T14:55:51.75Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/1c/eb8a032285243381b09a221ae384c972d5000453ad136add4d1595cec798/websockets-17.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5aefe78e6a3077fe22b5e64b04666a85a3eb8b934d40e8595a693adcbceb6f11", size = 228574, upload-time = "2026-08-26T14:55:52.922Z" },
+ { url = "https://files.pythonhosted.org/packages/69/85/413736251cb3ac04ce84cbd90e893d9a36a9698d4820b323aff3aa187e50/websockets-17.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f64e001bb7fa89b9f32cfa600bf8e9ac8ca26759d9b92ae01453ee303d9cd7b4", size = 226428, upload-time = "2026-08-26T14:55:54.263Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/2b/a08bcc7fa1ca81a10f84ba32b6e6edd73a913f4b0c2640eed1fd626efacd/websockets-17.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:677014a073bcb1fbaa7e21144786864f16c08f856d66834f611eceb9006cbab8", size = 225184, upload-time = "2026-08-26T14:55:55.943Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/8a/3bd2d0cf6b148c8c866d5d9fdcde30c04bfd81fdfac86813e69377eb4448/websockets-17.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0de501b7f2db11e83739ac20e2d33d46da4604b829f506c24be80e7def069391", size = 222430, upload-time = "2026-08-26T14:55:57.103Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/c9/8e891ae342668735eabbbc669895e15195e4b45f24a4beeb58af76f414c7/websockets-17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f62114a54117e4948a1e414e89521f7fe1e3c2f83f2a571a06a4fc6718b0900a", size = 225227, upload-time = "2026-08-26T14:55:58.375Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/6f/c816f332dca11425e9bda7c07f7573eb5c5f8a735849d02b0d81e8ee20fa/websockets-17.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:eec113a5b41d124ef42ff56b0d74a6da3fd986400038eab9e58ee42a4024e837", size = 223831, upload-time = "2026-08-26T14:55:59.664Z" },
+ { url = "https://files.pythonhosted.org/packages/53/67/5e91d5308ce24fc1ec74f56536c12f4888bad45ff5ea50f3180f8c518c57/websockets-17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5f051f8030a51815dc00e24bd2e5f1435af095c1cc111d747ac6e2a3620d7641", size = 224600, upload-time = "2026-08-26T14:56:00.873Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/96/faa298ecf2570d35b0eb37caddf4992178d907e108ed74bfffb6bc092c29/websockets-17.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:655a8e28010f09fd6fa317e857afab3af7647f33e41dee88fa421e92086d1090", size = 225707, upload-time = "2026-08-26T14:56:02.001Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/12/5710d2482ca5061c1eec5eb46f6313837c760d4115b1795c85b6c08be4e3/websockets-17.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:dc2b79afc074d2f3e64b26539350f697fe1b85ea1c49ea24eb588f247b053ce1", size = 223263, upload-time = "2026-08-26T14:56:03.092Z" },
+ { url = "https://files.pythonhosted.org/packages/27/47/0c30f4eebfd1d93fae779d268f678d48847fb98516f5200849574eee8820/websockets-17.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e4bd7eacb87d8cf3ed70d6392c770a0d92441f05d7d2a3efafb5bc171d5e3067", size = 224244, upload-time = "2026-08-26T14:56:04.321Z" },
+ { url = "https://files.pythonhosted.org/packages/41/33/46c256195a1255079ae23d1b1267b2e1843dc5f46a67f973cdf2a3523dff/websockets-17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ccbf3f4a9890d50b3a08ee04029fde30a03bfdeffaa19977628bf17251764e60", size = 224520, upload-time = "2026-08-26T14:56:05.521Z" },
+ { url = "https://files.pythonhosted.org/packages/06/9a/aef0792731df4352e5f417369b532b3325fe434765ca90c193f594ae1e67/websockets-17.1-cp312-cp312-win32.whl", hash = "sha256:7e724f843fa6a0614aece65a7c73e51d0f4412ca41dccac13c3caf98e69536bb", size = 217485, upload-time = "2026-08-26T14:56:06.715Z" },
+ { url = "https://files.pythonhosted.org/packages/50/23/493ecfdaf32898e5ea24dc900e33e5e317f9662d5d9ab2d44b2e111b4e1c/websockets-17.1-cp312-cp312-win_amd64.whl", hash = "sha256:617243e19a0992095956f406ee9cd3bc4ba92862d83cb1d83bb59ce574412bec", size = 217786, upload-time = "2026-08-26T14:56:08.055Z" },
+ { url = "https://files.pythonhosted.org/packages/97/3d/91954e2f7876f74ce1213e9b92c65a63b559cc4b942a931ebeb351cd9932/websockets-17.1-cp312-cp312-win_arm64.whl", hash = "sha256:9f4a08ff7cb68c27b18e09223cc6304e01d0f82d5a240d251266dfd2e6e44729", size = 217711, upload-time = "2026-08-26T14:56:09.267Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/31/5f6450a7879f4f063ef08897cc385ea3ce3f1fe17f08b11e3fd959abdf27/websockets-17.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a0162a6372110a5601cb5c9fd826635cedf69f3e110c545dd19774e040b970e", size = 217006, upload-time = "2026-08-26T14:56:10.509Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/2a/c1b006fc861695d2aa4e35327b842015ce1d98cf8f99241829b3d6460bfc/websockets-17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:829dba1bc049779de9b332088c1a6a9858e96bd67e50b6b644a95e02b67836bc", size = 214690, upload-time = "2026-08-26T14:56:11.681Z" },
+ { url = "https://files.pythonhosted.org/packages/46/69/66e5b7d01445e0eeb1d4ab419c30315f2c90cf7a8a8cd4ecc47f894dba54/websockets-17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fd8f47dbf2e8adb15c847215f83436de3fdb120b51fdae0fbbdf69fd97a3ad80", size = 214947, upload-time = "2026-08-26T14:56:12.923Z" },
+ { url = "https://files.pythonhosted.org/packages/07/ce/033cafe2d2538562efa876b9149a2c7a0f7787870a4b1bb6e28adc9ceb6b/websockets-17.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9f4c0377a83e163a303514fdfab501dbe379bdc13e5b9312a91d112658b29dce", size = 224329, upload-time = "2026-08-26T14:56:14.212Z" },
+ { url = "https://files.pythonhosted.org/packages/34/c7/e1c2e8a67f6cc0aa43abe0046fb3b7a020980649e6a843751dc7ce9eb170/websockets-17.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c3241d684a76eaaef8b2dc789afde4343cd3aad55ea81e4e8ab3605b529bae51", size = 224611, upload-time = "2026-08-26T14:56:15.702Z" },
+ { url = "https://files.pythonhosted.org/packages/be/de/07c6d48eb3d2069709410c851e7de10ab83d752c4bd09862899627c2729b/websockets-17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e5f5c7a893507d0e83a80b88aefd6522f7e882cd53f9722c6f23f5a020c9557c", size = 225848, upload-time = "2026-08-26T14:56:16.962Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/dd/3c68572d20509648cc2fb6f50ccf3deeb4b87270f2c8966e99476e278ea3/websockets-17.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:00bf34b64501e3477e81fc281532ff3cbf4da26633c10b63979d5085d46602d3", size = 227290, upload-time = "2026-08-26T14:56:18.204Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/4a/8f6651c8a22093539c9215af0c5bbf217b87b382c99d2112039b92d593c2/websockets-17.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ce0305b702b20d1e1d60a9aaace6bc89970e1753565543f310d549eab22c2435", size = 226476, upload-time = "2026-08-26T14:56:19.459Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/be/f6fc33cea86b1127fd1297b18c107e81580ab55a73a39f9a934441ef321f/websockets-17.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29176d8b429cfa0fa443c473878d37a5c06cfd0cb36b71ba4314accc71e05906", size = 225233, upload-time = "2026-08-26T14:56:20.939Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/83/65edaf05f7c9b1dea82f4d252fdc37706a84571646f06119a27b0a16fe19/websockets-17.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3709a1ab30b4b922027d22f68d2b61a0656a91680ac894a537624e6be7dd7f7c", size = 222488, upload-time = "2026-08-26T14:56:22.208Z" },
+ { url = "https://files.pythonhosted.org/packages/07/42/d1169c2f7f1f0032b0d4b0c00f0711a070cd7c735de37bfeb876bc0f9606/websockets-17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:43bd0c1ceb924d67f5c1a5254d8361dd9d94246e6331a726064dfa2917880780", size = 225295, upload-time = "2026-08-26T14:56:23.445Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/f4/64e2a386c3899b917c2933225c9b47887874229d159797f3bf1a11c20d51/websockets-17.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:1fce0f43e0d41422e0b2cad6561e1970df22f212f4c7e884967df7cf591b031c", size = 223891, upload-time = "2026-08-26T14:56:24.647Z" },
+ { url = "https://files.pythonhosted.org/packages/26/b3/dfb5c482f7e310a3432fdbb045ddfe6d34114680e89a233d4ff900a32961/websockets-17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4031152769179ab8dcdeafc7b0e58052a49117560a28671700b47b2c7b717aad", size = 224661, upload-time = "2026-08-26T14:56:26.027Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/cf/94865130a336029f46412adc127c4fbe380f46172b90ce251369e35c4302/websockets-17.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a06f3b5085176763182449559e20391d7ce616a8972a9f7a33deda87ea6d4f3c", size = 225766, upload-time = "2026-08-26T14:56:27.455Z" },
+ { url = "https://files.pythonhosted.org/packages/96/34/eb8c658f86dfe562ed49a887a27424bfe9e618c26ea6f865b093d075d3a6/websockets-17.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:77b37cceca17291897c3c73bd30a7c7c7909593554b5da574ec852af83c1742a", size = 223323, upload-time = "2026-08-26T14:56:28.807Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/7e/2629609652ece5ca0c7ac235927dd4511b08131e3a5d53439b798fddf002/websockets-17.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d8e83333385cac6030a5167fd18bf96cc6c58b914c308e683f05b0cf94bc8dd0", size = 224276, upload-time = "2026-08-26T14:56:29.991Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/6b/8525737fe840b38e5f40956c198fb586a4fac1e07144d41a5b949b989cf8/websockets-17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:073c5c3f7e127041fa9d34a9e29ceefee8c3cafbd267ed2927318f425144380d", size = 224558, upload-time = "2026-08-26T14:56:31.184Z" },
+ { url = "https://files.pythonhosted.org/packages/74/ab/3a958c6cbcf74b118f601c20a80ac8bd5e8dfec0bcf7345116feaeefb121/websockets-17.1-cp313-cp313-win32.whl", hash = "sha256:2afb58c7ba48b329d56769f8dfd89f394efe587b65ef806bae810a484d6d3608", size = 217475, upload-time = "2026-08-26T14:56:32.431Z" },
+ { url = "https://files.pythonhosted.org/packages/22/36/fb521f0f2994c25509651f169efe5582dddd8713d57a0757ba87859372ef/websockets-17.1-cp313-cp313-win_amd64.whl", hash = "sha256:0340bbef6bfbe16da888b3983d666a4db4954ac3253c38f13bc7aba0c7db5a2f", size = 217784, upload-time = "2026-08-26T14:56:33.608Z" },
+ { url = "https://files.pythonhosted.org/packages/68/92/9b8419584681a12a7534b746dfb2737c466efe2455483e2fbf8b941a04ec/websockets-17.1-cp313-cp313-win_arm64.whl", hash = "sha256:7a72efa3bf4fa3a6669a54420a472ad056da3973d827f10e3a536da463f926c2", size = 217715, upload-time = "2026-08-26T14:56:34.865Z" },
+ { url = "https://files.pythonhosted.org/packages/90/0d/500cf5daea09d4669dff3a7d67159094a0bd6c4ef130381404f6edd3eb5f/websockets-17.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0c9982938980e086da59f70d05f9418cd143401a601a0faac10fa48f7bb1cd3e", size = 217048, upload-time = "2026-08-26T14:56:36.03Z" },
+ { url = "https://files.pythonhosted.org/packages/97/12/5b12c6168aa269cffbfd24d177cd492b130120403a418c7e89462e27b4ac/websockets-17.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:57b39dc8541cf7ed3f639da82bf7451060483967f9e733da1f8173e4095f0642", size = 214737, upload-time = "2026-08-26T14:56:37.43Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/36/e453e5106e4e2416f008ac222837c2f1637a063b08008afcd1088889b631/websockets-17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:96abdecbaae746851b87c3a36cb4a661df93ca3d92f114270f79228bf1d00de6", size = 214955, upload-time = "2026-08-26T14:56:38.71Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/30/0204bb86176db02cdfc678ce65ed808a66fab87d250ce61a8790800a60b0/websockets-17.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d9fc873e239c5abeb150bc24dbd1a7af23a9254526383ce0a077f5e20adbeb19", size = 224331, upload-time = "2026-08-26T14:56:39.924Z" },
+ { url = "https://files.pythonhosted.org/packages/46/c8/d8372256e00c4e3cab1115c45075d1eeedb642a3f2b42bd70c4deae03f06/websockets-17.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6f42912fa9eb4cb7c7ec9fde9b3332ba339eb8a8811981043d4029599f3d950b", size = 224685, upload-time = "2026-08-26T14:56:41.169Z" },
+ { url = "https://files.pythonhosted.org/packages/12/7d/650355b8f67f908ff99603351d4458d1a0b787d627950a47c38db7e25308/websockets-17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f98bf378d7a5be047a044a1a27c987a8f355e10e3b5754617dbe756248cbc5ce", size = 225927, upload-time = "2026-08-26T14:56:42.359Z" },
+ { url = "https://files.pythonhosted.org/packages/34/6c/a9ffa5b903579eed76017870f055d75ecc73988d9d0c9b65a92ba0bf2a27/websockets-17.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d334d11398086bb5559606cb42d51c013ea7c061c7db701521392373d3c087f5", size = 227300, upload-time = "2026-08-26T14:56:43.538Z" },
+ { url = "https://files.pythonhosted.org/packages/9b/5d/4551c2269066af7481ee44605a0813770961615b5b5da3e87a8f5cb859ea/websockets-17.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c27336b1a0ac56569493e858497870347854372395f50483725f8cdacc5a45c", size = 226533, upload-time = "2026-08-26T14:56:44.669Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/43/237a99233e5c445759a613831b3a92e91905afc064dc3bd0ad33c35fd1e2/websockets-17.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:67258b00302a5aaf0b267771c7014b13429abd7ea17eebc4c55bd935ff101555", size = 225280, upload-time = "2026-08-26T14:56:45.83Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/b5/e9407a91613d1d1cd932414143a1012096b26674a782fc55a0bd23217ee4/websockets-17.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:455ffeea0879d313205df1e745e5883e1feb7f31ecd26be882f5f0babd3db04f", size = 222540, upload-time = "2026-08-26T14:56:47.053Z" },
+ { url = "https://files.pythonhosted.org/packages/db/d2/db76628db0577b783205d9779f64d8e373416b04c62d1546be4b75dc8540/websockets-17.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f7233eaf441a345a5943a929fd4b5ea3278f11aed35a9ed0f3106b8cb3ca846a", size = 225354, upload-time = "2026-08-26T14:56:48.32Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/4c/2174181c067b89a74ae18e2650c2ac29959f4b796afe876ab3f4d30d642c/websockets-17.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c65da239a5ad553619804c1f9d65c1a0b3005381c6158ee14da2c7444cbd0c78", size = 223867, upload-time = "2026-08-26T14:56:49.579Z" },
+ { url = "https://files.pythonhosted.org/packages/df/75/274decb9a8253561b5be3261e02a6676fc8ecdf31e95b722e53d5bfb8fd2/websockets-17.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9fa1ffa08c81a4f809cdab6129f8e55bee4650b9d6d3461019dda73aacd146b6", size = 224652, upload-time = "2026-08-26T14:56:50.885Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/e6/49824f1fb4db7656d2f7492b1d8be16147b759d909490e32f4776843ee64/websockets-17.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:406b8107943a43ef4649b1e0cb0cdc052bbf08fe1c8905a623c4af9586e5cebb", size = 225822, upload-time = "2026-08-26T14:56:52.356Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/6a/5dc43838c0b02a95f42c47a0de33c5ddd7767a9feeb4d0d8777ac1cfefe4/websockets-17.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:4e8ffcb486c8490a34a4cef5e4409d8da5a1cb1681e5bf7d786ce5e84aa8540d", size = 223379, upload-time = "2026-08-26T14:56:53.699Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/62/585637cf06d6b321232f79c55dc14d65518d12cf87c94c44f5864068810e/websockets-17.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:fb88076df585b69c5761c387c0081aa87d7b9eb1b205a6535ca4777e25650d81", size = 224330, upload-time = "2026-08-26T14:56:55.184Z" },
+ { url = "https://files.pythonhosted.org/packages/de/68/c3b234a6a1366b6ab5bbfaa4434a1b946e1dc4e8ddd6824bfd93a8835b7f/websockets-17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5d4724255fb8398acd9e583b97eb2279cec20e0bd0f9a94bf75f6056ef9f13da", size = 224622, upload-time = "2026-08-26T14:56:56.393Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/d4/84cf3d1376f5d8207f55f43c1c818babd6b89447f5dcd01f18a6d5526796/websockets-17.1-cp314-cp314-win32.whl", hash = "sha256:be3f0129c5654517b2abf07dcb75bb1d9479759a4ccfb569e8293579e9fc029a", size = 217036, upload-time = "2026-08-26T14:56:57.652Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/0f/9e7ac63c5d7cb642952200814f584318e65146df008b7d375d5d9c6b2c97/websockets-17.1-cp314-cp314-win_amd64.whl", hash = "sha256:2a4dc6ef83f4559e0d05f313a375cb38f63c986096a9da99fe94fdd779d313e5", size = 217382, upload-time = "2026-08-26T14:56:59.065Z" },
+ { url = "https://files.pythonhosted.org/packages/54/bb/1ae6b91f7f3ac05f5c9f14a72dc2181c115ff370bcd8a7f10f02c174adfd/websockets-17.1-cp314-cp314-win_arm64.whl", hash = "sha256:46c0331c9eaaf73a559f3a9e388466be0df96eb83d40f06f1ca6ab6613b35c82", size = 217268, upload-time = "2026-08-26T14:57:00.654Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/f0/f65644d0e0b2b90918a8c41503841cc4072a58f2bf76c09bc36e751fc0dd/websockets-17.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d411ea5ca18ac1b12c0c94be88b60c18ca641ac43bcdfdf1c9f79d46cdbe1603", size = 217379, upload-time = "2026-08-26T14:57:02.181Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/35/4c46d1f620ac1a30f92b6eae78ee40a772a93f568647ca7ccdc5ea283cf8/websockets-17.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:07fa3e7c30e2c577928d359b56bf872a3e0cbcc15553eaa0907c1ee86344b56f", size = 214911, upload-time = "2026-08-26T14:57:03.478Z" },
+ { url = "https://files.pythonhosted.org/packages/04/6e/4587e8406d7c1188e97b9cf466c081e93399380d447f885bfce81626cd37/websockets-17.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6de9acef07e3a78e9567fcd26c29011a4da8f050b13004bbf880a0fd82a6eea5", size = 215115, upload-time = "2026-08-26T14:57:04.692Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/06/1381c8fff525041025909eb80ace32489194a00ba22a0a8d428030afcc84/websockets-17.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ea0ed9373b880115911d9d39634bccc95b8ce590c9c42e8589f5cacc3ef3cee2", size = 224696, upload-time = "2026-08-26T14:57:05.899Z" },
+ { url = "https://files.pythonhosted.org/packages/36/9d/9034e867dc85340be058619751742b895f722326e83100d110063461ca07/websockets-17.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50903d335bfda026c2fa11dd9aed09d8cbee0c451e3a85122a9acb041b7dc69b", size = 224975, upload-time = "2026-08-26T14:57:07.262Z" },
+ { url = "https://files.pythonhosted.org/packages/40/eb/ed03aa3cae748ebf6397e5d44028f433f746bad09dc568ff754fda3a3c9b/websockets-17.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a74531ce81af587f906ab42f194032388fcff8fc7938402e5917c9147a39441", size = 226151, upload-time = "2026-08-26T14:57:08.524Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/c9/cc1964a096d16f3b73cb1ee5f14f277f5a3bcac07c6e8f9a1dcded99f4c8/websockets-17.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8fbf28e639544503b7d1c96452a5e5e043e4108d89b1f3fa02910603622d19db", size = 228292, upload-time = "2026-08-26T14:57:09.846Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/26/46da6dd0363c2db2e4876fd59a40fd40c1943a82d7018d0a33afbce47d52/websockets-17.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f612dc57f00c07cf4aa2673f7cbceabd654ad2457b7e639f061b794d6e11f9fd", size = 226722, upload-time = "2026-08-26T14:57:11.118Z" },
+ { url = "https://files.pythonhosted.org/packages/78/98/ecd8f5e1c5d0e54c08ebc5c66852271112166db68107cb0e17ca1bf25009/websockets-17.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1c7ac77401227212dc6e849182feee50d57cf456ec6329ffd6979c94bb136c5c", size = 225451, upload-time = "2026-08-26T14:57:12.601Z" },
+ { url = "https://files.pythonhosted.org/packages/65/4d/da8d2760db53e17aae763738b6ba834b1fcf16813d3632f3edb6951e1ec8/websockets-17.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32a2a68d989d6e5b74a9d5095415c51189ebae29fceb7cf2b64a1c0318a81256", size = 223003, upload-time = "2026-08-26T14:57:13.875Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/40/ea401c141a79c5b1d0021a0dab9d0df2051c108f1620fbb39a6e7c714c3b/websockets-17.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:aec00f018d34c67500ff0438dc314b40277be4a1b983cbacbf53ccf7db63e257", size = 225704, upload-time = "2026-08-26T14:57:15.091Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/8e/07ab3f44215d89840d5385fdcaaab1fed8caeffa67c6899e15062957c12c/websockets-17.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:0014eaff8ad5b3b43feda2279f9d34bf2eaae040720b9fbbb55944b10f40b14d", size = 224192, upload-time = "2026-08-26T14:57:16.3Z" },
+ { url = "https://files.pythonhosted.org/packages/58/93/ccf1af0a23e5748d4e22292a377d78d15cf294d7e707bbb11a8990ae6bd5/websockets-17.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:db9d7ee47f3ba531e278be539af39e2c7c7d28fb94897b6cd1120d63b0ef5922", size = 225082, upload-time = "2026-08-26T14:57:17.531Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/db/e32200f99ce282e728d2929f2c429db353cf3282db7d0eba99eb32c9fec1/websockets-17.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:ff3e2ba7a9f0a110b0555452e9b5a03a34e11662544e01beea15f144b48ba7b7", size = 226101, upload-time = "2026-08-26T14:57:18.802Z" },
+ { url = "https://files.pythonhosted.org/packages/28/3d/e7a6e9777b29433620167c98f3caaff0d6b08b1239a273ef7f7fd1393349/websockets-17.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6da17fc94bd270f5987b10bee113461ac36a36a98b0481ddcc98056e5a90001a", size = 223794, upload-time = "2026-08-26T14:57:20.313Z" },
+ { url = "https://files.pythonhosted.org/packages/48/05/ac569090726dedd6656f3ee28b0c02dfb1ba76e898dceaccc2987a237cef/websockets-17.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:e8dc3fa6d6b7ead3f9de57895f41b116a28787548e066365d9d90f7356bcaad2", size = 224567, upload-time = "2026-08-26T14:57:21.634Z" },
+ { url = "https://files.pythonhosted.org/packages/14/50/4ef62941111db6b31193f4fabbb65f845a5177579040cb8fe0d774d25034/websockets-17.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b65d5fe48219dc2d5e158de9e6514e75600f379cc7e37108d35f31764c155566", size = 224993, upload-time = "2026-08-26T14:57:22.86Z" },
+ { url = "https://files.pythonhosted.org/packages/28/42/2b95ada4ea19bf3a2072b68669ce4f4afb212690b727d31640576287fd68/websockets-17.1-cp314-cp314t-win32.whl", hash = "sha256:2cce251f3e2469b99b6802b55435bcdd07123b41870f54c87b336183af9d7e68", size = 217168, upload-time = "2026-08-26T14:57:24.466Z" },
+ { url = "https://files.pythonhosted.org/packages/32/0a/67d5ee08dd8060a37d612fd40a625b5376ad19ae48fe1c8ad428c278b817/websockets-17.1-cp314-cp314t-win_amd64.whl", hash = "sha256:8f6c38cdcaf98a911d7acc25577f2f9e710f3a2fc2bde1563556784320196b51", size = 217508, upload-time = "2026-08-26T14:57:25.983Z" },
+ { url = "https://files.pythonhosted.org/packages/76/a3/822005d0c674451d2411027b878cdc128a2b7ea5a30d337d9e279da22eba/websockets-17.1-cp314-cp314t-win_arm64.whl", hash = "sha256:d1e2f5fa2b6d01f0d85b4f223fea7ed1d504be282a02a81bd2be4817ef7a2f03", size = 217425, upload-time = "2026-08-26T14:57:27.324Z" },
+ { url = "https://files.pythonhosted.org/packages/de/d5/99a6c6a1eb5d5ae9f45f59a3c97f4e3b21f310eb404a547fb3e7d2fc054c/websockets-17.1-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:88381602e379165b66244b2ebc29f9b23ea0851fbe63ae157f91ca324f072d6f", size = 216970, upload-time = "2026-08-26T14:57:28.575Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/0e/1e7f6e833728193958d3ed3d67b5d57c3c7cfa948abf94d4bc553257c954/websockets-17.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:88bc5138e53903a85c354e59df7ba73ce306f7b09724cef74dba121e60a88ce2", size = 214699, upload-time = "2026-08-26T14:57:29.862Z" },
+ { url = "https://files.pythonhosted.org/packages/07/00/95d39549f86e34425a0412bcbe61708dd1fc46af654e2134a6c4389102ad/websockets-17.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:3546ef55b3a074494106508bc6505c73825970d2d9505f7bf53882b3e88b0d1e", size = 214927, upload-time = "2026-08-26T14:57:31.148Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/ff/b442415fc4f7f9943b0fc8e8eebaa13923ca73361e167c439ba634eecbd9/websockets-17.1-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9ae55d24241fc055f22aea3ac924559069848bd0ad4ea065fdd72d2194685fe8", size = 224373, upload-time = "2026-08-26T14:57:32.833Z" },
+ { url = "https://files.pythonhosted.org/packages/a8/dd/b83537aae4cf61615b9d8b2dbb235c0030ba85457a6d934798273814600f/websockets-17.1-cp315-cp315-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d7b349265fad6244013eecd99df8d83c12bf3013943e431f4fadd5bffc37db42", size = 224801, upload-time = "2026-08-26T14:57:34.041Z" },
+ { url = "https://files.pythonhosted.org/packages/76/83/5ab0abed58454909e8dbab45086ac68ee4556d7a8ada26735addc909b903/websockets-17.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc5789e5ea182b77a38881383ada5347202a6c66f4857d054e075290e80b604b", size = 225967, upload-time = "2026-08-26T14:57:35.292Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/26/e2412f2b998a8c1dfc00c0709ff6ee0c634dd0b0b4f92bdfe9667876b71c/websockets-17.1-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ce13c7d233239e739600a57d4a73c1192ad8259e655a4d55aa1a454242bc809d", size = 227664, upload-time = "2026-08-26T14:57:36.493Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/25/0dd4495df3c0e02f6db705312ba85ab9b2dd42257dc23eb0da10066e4844/websockets-17.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1036189bd34b0bc1b10a4679321e2c7968af317efe6e8e4c1c5141c4254fb5bb", size = 226447, upload-time = "2026-08-26T14:57:37.781Z" },
+ { url = "https://files.pythonhosted.org/packages/be/67/6df3f63ffc48f08126ed0cd2fd2a41092967c3e364f8ec100deae90b6d77/websockets-17.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e78fd4b7b2c5086a38671c9c882c1e643385eccea360b5b1fda4a105e590087e", size = 225343, upload-time = "2026-08-26T14:57:39.133Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/8d/a8479bbb09ff054907d141123d8f52fb6ae5ac39c6dbe39e6a02a8408309/websockets-17.1-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:46e7a10bf04318c7b0c0273791925ae5e1cbe4a11e34aa934d2ef27862058a80", size = 222748, upload-time = "2026-08-26T14:57:40.478Z" },
+ { url = "https://files.pythonhosted.org/packages/40/fb/4c3d2a3269cde3f3087916de9c3d9fc5d7196b46846d8c3a9ae59ad0a884/websockets-17.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:33e45c7ea38428e740a7f233555d71df0b875cef7fc080acebc9654475e35335", size = 225453, upload-time = "2026-08-26T14:57:41.859Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/1c/6467b401d19408f34e1c7389c222c2c7e1dfdf08c551190269b5eabc726c/websockets-17.1-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:6e63c01803be425ff062b7f7fc201a74def1d49fc94a2410dd17375df75936e9", size = 224112, upload-time = "2026-08-26T14:57:43.136Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/5f/744e032ac80e11039a7447657ebabb46e9b5c2dbcec83be571335212932f/websockets-17.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:722ec21717eec6477bce582147a28acdfe034e604239466a6a95daedb863e774", size = 224646, upload-time = "2026-08-26T14:57:44.871Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/47/bcb9128d9afc4d0934d9192e2a24897ca2f7a63df2654904915349c6c46d/websockets-17.1-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:e74e41f0ad12ff1e8983e349daef79d37cc8280c743ce9d134d6c74c18dab5d6", size = 225797, upload-time = "2026-08-26T14:57:46.338Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/e0/b058047b7cf565e1105b10ef6b6b24a6ebe3575678c7dc75a645334705a7/websockets-17.1-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:12fe8984a32dbfd084e0603f1a8d740c0180cb85b3174585c54a80d2455a8394", size = 223605, upload-time = "2026-08-26T14:57:48.175Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/69/fc1555bff884de363f1bf9eebf2836dbeb29fa7e4f957debb7bbcf43abba/websockets-17.1-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:01dcb47deebc40b38fd4a493b9b9f4d0a704b7bec6f35e4d34085b329abce71a", size = 224508, upload-time = "2026-08-26T14:57:49.407Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/f9/648d4e68621688b19093b06f7b497d520952e68cdea1c1b54371fe9491de/websockets-17.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:f4c45ee2512d3757b5e6c67c5a34e435143f2ecb7df3324f9fd888688c45c0f4", size = 224767, upload-time = "2026-08-26T14:57:50.799Z" },
+ { url = "https://files.pythonhosted.org/packages/58/93/f8342b55864f71df13eb8e9ef7dce691b87a87f04f75bb8a1385b3336e7c/websockets-17.1-cp315-cp315-win32.whl", hash = "sha256:0f4f50dfe2cc810fc4e2de979b35e83bf8bb4bccdc6fe472d93762ea7b1d5927", size = 217003, upload-time = "2026-08-26T14:57:52.122Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/f0/7b5fdb774c245e0b6217009e2a24d2105c1a64923949f33be41aa7959302/websockets-17.1-cp315-cp315-win_amd64.whl", hash = "sha256:4af784f3e436f65b355c117c6497320f2b5cf6a559295cb1c4c7338e335d45cc", size = 217300, upload-time = "2026-08-26T14:57:53.492Z" },
+ { url = "https://files.pythonhosted.org/packages/76/33/1fe6ed1b5087516115ca451b2c240314b010647071f8fc3bd78a21e4dddb/websockets-17.1-cp315-cp315-win_arm64.whl", hash = "sha256:d58159af7835fde09c462394293c0d7aaf8fb4557d8f8e5699f5e722ccae013d", size = 217214, upload-time = "2026-08-26T14:57:54.88Z" },
+ { url = "https://files.pythonhosted.org/packages/94/ca/ed02e75996a266d76c5fcb5dd9b930db4cf2b388ca5fa3d2a72086f81568/websockets-17.1-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:1a5cf4e7bbe3ca499e6a289206cb4fcb7444b09919e129bd517f57d5fa192c13", size = 217282, upload-time = "2026-08-26T14:57:56.108Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/7d/d536f5bc89ea5b52fd1c1727c59fabafee6bc41f5ce92c3bd2f83047908c/websockets-17.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:416b4bc8789a1865a3ff643ec4ee073a5f52402d0dbeafd27b1798d5dd6b6a51", size = 214863, upload-time = "2026-08-26T14:57:57.355Z" },
+ { url = "https://files.pythonhosted.org/packages/37/37/944cf17bad668e9be1247e6314f88a48b9faf7c250e383410db8b38af0b9/websockets-17.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:259f45358c76d3b18489e3e80636cdbe807e05ecf1b10fdf1a779106d23d0c8e", size = 215073, upload-time = "2026-08-26T14:57:58.719Z" },
+ { url = "https://files.pythonhosted.org/packages/74/bf/3267966cc1bbc2b8fa62fd329651b0af502df1f5d1c0eed027ff339d6aa8/websockets-17.1-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d9d01e8ede41fea4f5a847dad9d628355f74905f437a5b6856d67aa66d193800", size = 225229, upload-time = "2026-08-26T14:58:00.235Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/d8/85ea722f483510abb39fc71aafb4465d17cf9051a275ab036874ff3c300c/websockets-17.1-cp315-cp315t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a7b35181a14cbfcae163b4de545d22abfd07d06c2c41ca69cfcd99251d6888ab", size = 225500, upload-time = "2026-08-26T14:58:01.994Z" },
+ { url = "https://files.pythonhosted.org/packages/50/ce/64c7d00005bd0d15ecb5c5fcb7fb2597b6b92ddd16c4fa6bbc3d2835ad63/websockets-17.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a8e768a048c2220697477ce2e67e4345dc9f693d0ee6af53945b5e30227c6a7", size = 226829, upload-time = "2026-08-26T14:58:03.327Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/dc/096c67940fb957e667ca3c542818150434eb0388c6fdc90b3a502f3c3e96/websockets-17.1-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:880069d21cc33a558dcf180924a546d1ecf8ada5be3e4e70acee87019d706a24", size = 228457, upload-time = "2026-08-26T14:58:04.78Z" },
+ { url = "https://files.pythonhosted.org/packages/51/fe/f2331b6b7ccc67589891da354fa46a5cb79e95f83b9fd0e734d77f1f2140/websockets-17.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cec1bb8f22abccc8d20f8ca63df9be41600c26c190f4b97ee86c675fd4a863a6", size = 227265, upload-time = "2026-08-26T14:58:06.102Z" },
+ { url = "https://files.pythonhosted.org/packages/47/a5/fb1642302f8ec77ca922203074f155a9831a5128ad75e725059a476d1227/websockets-17.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f3a1d577e081667dda7f8e5b4796e6e32f9713c93e2a3d930669519840a3c623", size = 226143, upload-time = "2026-08-26T14:58:07.464Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/41/7133fcfb63f5562750b269d6a845c689dde6a2c6407286da395beea19ddd/websockets-17.1-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc053f9e95a76213c5eb7ed95779f7daf0d2bf0e4e03073629ebfa43a033f151", size = 223501, upload-time = "2026-08-26T14:58:08.766Z" },
+ { url = "https://files.pythonhosted.org/packages/64/b1/82b36bfabc79ff2d383a1fc043cee6a13f794ef4f6bf1b4810ad6988cf6f/websockets-17.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:bb0efe019480a1c93e168ce96479273aaebd672fc8c350d5eed1e507ababb1b8", size = 226330, upload-time = "2026-08-26T14:58:09.987Z" },
+ { url = "https://files.pythonhosted.org/packages/41/7d/5b511b9bf6e9ad331e6ff902fcbcc71c3794d10ef3b5efe80ccb8f0a7861/websockets-17.1-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:615746b12b26a3fd4077bc6fbeb277a1c192a45dd57b531d07ad9ed5c52a9a7a", size = 224980, upload-time = "2026-08-26T14:58:11.303Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/50/aed08f25301f8eef23be903ff9319fcf35630ca2bdec9d226f7d804dd5b3/websockets-17.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:1a20136d61f9ca3a31493732762661fafc2c20e8861930214e21afc6a8a692a2", size = 225478, upload-time = "2026-08-26T14:58:12.543Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/47/0d63d4168536b4682c9d19b7399443b1176f25dbb68878374fa716670230/websockets-17.1-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:2786cbd273ab69c22612db8a41229ddf2c158060b17b5928884bf388d07887f3", size = 226588, upload-time = "2026-08-26T14:58:14.457Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/dd/844bd0b6386fc81ed6a55f4b6dd26f01c6987eda205afa10175ea12b2164/websockets-17.1-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:b1c323fc3be1dc3f87f6c59458cb7d9e13dcbbf971d6c3f3e2bbaf58d3bfcdfe", size = 224336, upload-time = "2026-08-26T14:58:15.778Z" },
+ { url = "https://files.pythonhosted.org/packages/96/18/03709c84bc88ec4dcea68d4be4ccd07d611073dec111203a5bf45af8809d/websockets-17.1-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:12c8e2b25df59755954a04dfa09c990b96691025aaf7eafd19ed6da24b09c18d", size = 225197, upload-time = "2026-08-26T14:58:17.141Z" },
+ { url = "https://files.pythonhosted.org/packages/27/cf/0d1c694b6466c89e875b85b32b51312c472cf6708eee91914866f5087dde/websockets-17.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f58f58b4b29bbea2a3635e2c56eff4a3adab011fe383802a9e542e31b97085fc", size = 225493, upload-time = "2026-08-26T14:58:18.521Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/f5/99857c3dd9676749f33e3668665a34ad6099505fb8d75eb084f49f7807a9/websockets-17.1-cp315-cp315t-win32.whl", hash = "sha256:f78a3ffb1994304db2c0c4588e4d1a518079b557054fa3bb985a6f5e50ff49a3", size = 217130, upload-time = "2026-08-26T14:58:20.037Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/84/77599922ab441bfe61508f97dab2c71f8e114d31793993ea54011db16199/websockets-17.1-cp315-cp315t-win_amd64.whl", hash = "sha256:ad68c28a27246fed109a4409393d677b7e1388345cbbd2f5aee5c182d8506110", size = 217448, upload-time = "2026-08-26T14:58:21.382Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/3c/8b9a225b523f06a9389be81f1b0ab07c49bec6014742e6aa359c1f920f1f/websockets-17.1-cp315-cp315t-win_arm64.whl", hash = "sha256:e552e0037230ac16e5f568de7012041344d1b18c9feed30ec2891b8eba55af81", size = 217372, upload-time = "2026-08-26T14:58:22.807Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/e4/af4abbcf07eac6a725ec6f865611526b2b0c23d482723de551bec667880d/websockets-17.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10ecb38ffc05e1841b619d99c725307a223ef9ad58e7b1ed33311d472dc43918", size = 214602, upload-time = "2026-08-26T14:58:25.211Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/fe/819fba7ba35f92b639333da7355041c07dd50048f9c76fba0b8e292a6483/websockets-17.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17aa424ab61620aad21b36b2240efc87b500cc496e7d0e999a5c2ae99395e886", size = 214874, upload-time = "2026-08-26T14:58:26.689Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/a7/d370ab794f47fbeea648d17ad08caf0bb50131d6c04b7ad83e6af63c405a/websockets-17.1-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:764cf7bfa149365f32b7a0fd9fed32debdac29dd06295d5635cde1745b446cd8", size = 215821, upload-time = "2026-08-26T17:25:23.616Z" },
+ { url = "https://files.pythonhosted.org/packages/9b/6b/251b00fe634e2a9c2cb5d6390e0e97cec55e3d18dd09b4b976620eed5d7b/websockets-17.1-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8d1b108bd8f5f6a8b90801f6db3b3858d5deca889acfdb8ac497bbb24e4b0edf", size = 215714, upload-time = "2026-08-26T17:25:26.295Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/b1/37fe0c96c206b4208a072c3a74add6a72af4b8228be3f5435163c5a6d099/websockets-17.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a62d8c424383c9dc769ff3672018df822603117e32686e567d452ed035b6fb2e", size = 216608, upload-time = "2026-08-26T17:25:28.134Z" },
+ { url = "https://files.pythonhosted.org/packages/be/7e/75a0a491b512412e08333b9f8412757af6186fe1c598186261002de1a793/websockets-17.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8196d217eeca52b9235ee1f8a684a09885a5f953d5a31e80ef915bf2c5c94f9d", size = 217870, upload-time = "2026-08-26T17:25:29.745Z" },
+ { url = "https://files.pythonhosted.org/packages/41/63/23572870e01836a98346075b9e17a8bc24a6ddd9800a3204ceee58677f3c/websockets-17.1-py3-none-any.whl", hash = "sha256:f221081107b8c48184d99f7019604486376e7ef826037e70aad6b02540732c23", size = 211134, upload-time = "2026-08-26T17:25:31.397Z" },
]
From afcc9e41ea27854cb10b49fec17d86be766b9c73 Mon Sep 17 00:00:00 2001
From: Sean Keever <33592180+swkeever@users.noreply.github.com>
Date: Wed, 26 Aug 2026 18:35:36 -0400
Subject: [PATCH 2/6] fix(test): use supported Behave step patterns
---
tests/unit/test_contract_bindings.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/unit/test_contract_bindings.py b/tests/unit/test_contract_bindings.py
index 606b9533..959ac3ca 100644
--- a/tests/unit/test_contract_bindings.py
+++ b/tests/unit/test_contract_bindings.py
@@ -41,7 +41,7 @@ def test_every_contract_phrase_is_bound_verbatim() -> None:
registry.clear()
_load_module("contract_steps", ROOT / "features" / "steps" / "sdk_contract_steps.py")
bound = {
- definition.string
+ definition.pattern
for definitions in registry.steps.values()
for definition in definitions
}
From 1b804904522c0b925eb176420a0731c402ccfb5a Mon Sep 17 00:00:00 2001
From: Sean Keever <33592180+swkeever@users.noreply.github.com>
Date: Thu, 27 Aug 2026 12:12:11 -0400
Subject: [PATCH 3/6] fix(realtime): harden lifecycle coordination
---
features/contract/auth.feature | 1 +
features/contract/storage.feature | 1 +
features/steps/sdk_contract_steps.py | 27 ++-
src/volcano_sdk/realtime.py | 157 +++++++++++----
tests/unit/test_contract_bindings.py | 6 +-
tests/unit/test_realtime.py | 281 +++++++++++++++++++++++++++
6 files changed, 434 insertions(+), 39 deletions(-)
diff --git a/features/contract/auth.feature b/features/contract/auth.feature
index 6c5f17b8..c24af106 100644
--- a/features/contract/auth.feature
+++ b/features/contract/auth.feature
@@ -6,3 +6,4 @@ Feature: SDK authentication contract
When the client signs in with the contract user's credentials
Then the SDK operation succeeds
And the current session belongs to the contract user
+ And the current session exposes access and refresh tokens
diff --git a/features/contract/storage.feature b/features/contract/storage.feature
index 80972145..bcc24941 100644
--- a/features/contract/storage.feature
+++ b/features/contract/storage.feature
@@ -6,3 +6,4 @@ Feature: SDK storage contract
When the client uploads and downloads the contract object
Then the SDK operation succeeds
And the downloaded bytes equal the uploaded bytes
+ And the stored object path equals the contract path
diff --git a/features/steps/sdk_contract_steps.py b/features/steps/sdk_contract_steps.py
index 82d3cab3..6eb76062 100644
--- a/features/steps/sdk_contract_steps.py
+++ b/features/steps/sdk_contract_steps.py
@@ -48,6 +48,15 @@ def session_belongs_to_contract_user(context: Any) -> None:
assert world.client.current_session.user_id == world.fixture["user_id"]
+@then("the current session exposes access and refresh tokens")
+def session_exposes_tokens(context: Any) -> None:
+ world = _world(context)
+ session = world.client.current_session
+ assert session is not None
+ assert session.access_token
+ assert session.refresh_token
+
+
@given("an authenticated client")
def authenticated_client(context: Any) -> None:
_world(context).authenticate()
@@ -76,10 +85,13 @@ def fixture_row_returned(context: Any) -> None:
def upload_and_download(context: Any) -> None:
world = _world(context)
- def operation() -> bytes:
+ def operation() -> dict[str, Any]:
bucket = world.client.storage.from_(world.fixture["bucket_name"])
- bucket.upload(world.storage_path, world.storage_bytes)
- return bucket.download(world.storage_path)
+ uploaded = bucket.upload(world.storage_path, world.storage_bytes)
+ return {
+ "bytes": bucket.download(world.storage_path),
+ "path": uploaded["name"],
+ }
world.record(operation)
@@ -88,7 +100,14 @@ def operation() -> bytes:
def downloaded_bytes_match(context: Any) -> None:
world = _world(context)
assert world.last_outcome is not None
- assert world.last_outcome.value == world.storage_bytes
+ assert world.last_outcome.value["bytes"] == world.storage_bytes
+
+
+@then("the stored object path equals the contract path")
+def stored_object_path_matches(context: Any) -> None:
+ world = _world(context)
+ assert world.last_outcome is not None
+ assert world.last_outcome.value["path"] == world.storage_path
@given("a service-role client")
diff --git a/src/volcano_sdk/realtime.py b/src/volcano_sdk/realtime.py
index 57d53d3d..327eb501 100644
--- a/src/volcano_sdk/realtime.py
+++ b/src/volcano_sdk/realtime.py
@@ -1,5 +1,6 @@
from __future__ import annotations
+import asyncio
import importlib
import inspect
from collections.abc import Awaitable, Callable
@@ -7,6 +8,7 @@
from urllib.parse import quote, urlsplit, urlunsplit
MessageCallback = Callable[[Any], Any]
+CALLBACK_QUEUE_LIMIT = 128
class RealtimeContext(Protocol):
@@ -145,6 +147,12 @@ def __init__(self, realtime: Realtime, name: str) -> None:
self._name = name
self._message_callbacks: list[MessageCallback] = []
self._subscription: CentrifugeSubscription | None = None
+ self._callback_queue: asyncio.Queue[Any] = asyncio.Queue(
+ maxsize=CALLBACK_QUEUE_LIMIT
+ )
+ self._callback_task: asyncio.Task[None] | None = None
+ self._active_callback_task: asyncio.Task[None] | None = None
+ self._callback_stop: asyncio.Event | None = None
def on(self, event: str, callback: MessageCallback) -> Channel:
if event != "message":
@@ -153,32 +161,86 @@ def on(self, event: str, callback: MessageCallback) -> Channel:
return self
async def subscribe(self) -> None:
- connection = await self._realtime._connect()
- if self._subscription is None:
- self._subscription = connection.new_subscription(
- self._name,
- events=_ChannelEvents(self),
- )
- await self._subscription.subscribe()
+ await self._realtime._subscribe(self)
async def send(self, data: Any) -> None:
- if self._subscription is None:
- raise RuntimeError("Channel must be subscribed before sending")
- await self._subscription.publish(data)
+ await self._realtime._publish(self, data)
async def unsubscribe(self) -> None:
- if self._subscription is None:
- return
- await self._subscription.unsubscribe()
+ await self._realtime._unsubscribe(self)
async def _emit(self, data: Any) -> None:
- for callback in tuple(self._message_callbacks):
- result = callback(data)
- if inspect.isawaitable(result):
- await result
+ task = self._callback_task
+ if task is None or task.done():
+ self._start_callback_dispatcher()
+ elif self._callback_stop is not None and self._callback_stop.is_set():
+ self._callback_task = asyncio.create_task(self._restart_callback_dispatcher(task))
+ self._callback_stop = None
+ try:
+ self._callback_queue.put_nowait(data)
+ except asyncio.QueueFull:
+ asyncio.get_running_loop().call_exception_handler(
+ {
+ "message": "Volcano realtime callback queue is full; publication dropped",
+ "channel": self._name,
+ }
+ )
- def _reset(self) -> None:
+ def _start_callback_dispatcher(self) -> None:
+ stop = asyncio.Event()
+ self._callback_stop = stop
+ self._callback_task = asyncio.create_task(self._dispatch_callbacks(stop))
+
+ async def _restart_callback_dispatcher(self, previous: asyncio.Task[None]) -> None:
+ await asyncio.gather(previous, return_exceptions=True)
+ stop = asyncio.Event()
+ self._callback_stop = stop
+ await self._dispatch_callbacks(stop)
+
+ async def _dispatch_callbacks(self, stop: asyncio.Event) -> None:
+ while not stop.is_set():
+ data = await self._callback_queue.get()
+ try:
+ for callback in tuple(self._message_callbacks):
+ active_task = asyncio.create_task(self._run_callback(callback, data))
+ self._active_callback_task = active_task
+ try:
+ (error,) = await asyncio.gather(
+ active_task, return_exceptions=True
+ )
+ finally:
+ self._active_callback_task = None
+ if isinstance(error, BaseException):
+ asyncio.get_running_loop().call_exception_handler(
+ {
+ "message": "Volcano realtime callback failed",
+ "exception": error,
+ "channel": self._name,
+ }
+ )
+ finally:
+ self._callback_queue.task_done()
+
+ async def _run_callback(self, callback: MessageCallback, data: Any) -> None:
+ result = callback(data)
+ if inspect.isawaitable(result):
+ await result
+
+ async def _reset(self) -> None:
self._subscription = None
+ task = self._callback_task
+ active_task = self._active_callback_task
+ if self._callback_stop is not None:
+ self._callback_stop.set()
+ current_task = asyncio.current_task()
+ called_from_dispatcher = current_task is task or current_task is active_task
+ if task is not None and not called_from_dispatcher:
+ task.cancel()
+ await asyncio.gather(task, return_exceptions=True)
+ self._callback_task = None
+ while not self._callback_queue.empty():
+ self._callback_queue.get_nowait()
+ self._callback_queue.task_done()
class Realtime:
@@ -193,6 +255,7 @@ def __init__(
self._api_url = api_url
self._client_factory = client_factory
self._connection: CentrifugeConnection | None = None
+ self._connection_lock = asyncio.Lock()
self._channels: dict[str, Channel] = {}
def channel(self, name: str) -> Channel:
@@ -211,21 +274,49 @@ def _address(self) -> str:
return urlunsplit((scheme, parsed.netloc, "/realtime/v1/websocket", query, ""))
async def _connect(self) -> CentrifugeConnection:
- if self._connection is None:
- self._connection = _VolcanoCentrifugeConnection(
- self._client_factory(
- self._address(),
- token=self._client_context._session_token(),
- get_token=self._token,
- )
+ async with self._connection_lock:
+ return await self._connect_locked()
+
+ async def _connect_locked(self) -> CentrifugeConnection:
+ if self._connection is not None:
+ return self._connection
+ connection = _VolcanoCentrifugeConnection(
+ self._client_factory(
+ self._address(),
+ token=self._client_context._session_token(),
+ get_token=self._token,
)
- await self._connection.connect()
- return self._connection
+ )
+ await connection.connect()
+ self._connection = connection
+ return connection
+
+ async def _subscribe(self, channel: Channel) -> None:
+ async with self._connection_lock:
+ connection = await self._connect_locked()
+ if channel._subscription is None:
+ channel._subscription = connection.new_subscription(
+ channel._name,
+ events=_ChannelEvents(channel),
+ )
+ await channel._subscription.subscribe()
+
+ async def _publish(self, channel: Channel, data: Any) -> None:
+ async with self._connection_lock:
+ if channel._subscription is None:
+ raise RuntimeError("Channel must be subscribed before sending")
+ await channel._subscription.publish(data)
+
+ async def _unsubscribe(self, channel: Channel) -> None:
+ async with self._connection_lock:
+ if channel._subscription is not None:
+ await channel._subscription.unsubscribe()
async def disconnect(self) -> None:
- if self._connection is None:
- return
- await self._connection.disconnect()
- self._connection = None
- for channel in self._channels.values():
- channel._reset()
+ async with self._connection_lock:
+ connection = self._connection
+ self._connection = None
+ if connection is not None:
+ await connection.disconnect()
+ for channel in tuple(self._channels.values()):
+ await channel._reset()
diff --git a/tests/unit/test_contract_bindings.py b/tests/unit/test_contract_bindings.py
index 959ac3ca..eefb6c92 100644
--- a/tests/unit/test_contract_bindings.py
+++ b/tests/unit/test_contract_bindings.py
@@ -11,11 +11,11 @@
ROOT = Path(__file__).parents[2]
FEATURE_SHA256 = {
- "auth.feature": "8e1b399dfc5062b59aca5c74f4ef17dcfd9442047ba6f14d0af95a3f44eb152b",
+ "auth.feature": "6e6bcc6244bbdb9b1c141a3f0d8f1256d2be0057429457084a094ed98cbcbd07",
"database.feature": "4685b29357a621068b25984ff0de29cd4c504eebe5cfb597f0b999e29878a668",
"locks.feature": "76fa31f9a7c203e33b367e5ca1467b2334e7c85c960de8d5cab8638920137411",
"realtime.feature": "e65862e27656cdd0afa8e552cb5a628d9831568e3299711e572ccd4f6b750696",
- "storage.feature": "a40db75b59dbd975185a3755345111a32c1e2b216ee5f5dd958c33dd3ef31457",
+ "storage.feature": "0772d46691d2a158e752d19cea995ff79db960fc3774c799ebdf081e19424d82",
}
@@ -57,8 +57,10 @@ def test_every_contract_phrase_is_bound_verbatim() -> None:
"the client uploads and downloads the contract object",
"the confirmed contract user",
"the current session belongs to the contract user",
+ "the current session exposes access and refresh tokens",
"the downloaded bytes equal the uploaded bytes",
"the released lease is no longer held",
+ "the stored object path equals the contract path",
"the subscriber receives the contract message within 10 seconds",
"two authenticated realtime clients",
}
diff --git a/tests/unit/test_realtime.py b/tests/unit/test_realtime.py
index fb5a3f51..f83d4af8 100644
--- a/tests/unit/test_realtime.py
+++ b/tests/unit/test_realtime.py
@@ -111,6 +111,10 @@ async def scenario() -> None:
"project-id:broadcast:contract",
{"event": "message", "value": "contract"},
)
+ for _ in range(10):
+ if received:
+ break
+ await asyncio.sleep(0)
assert received == [{"event": "message", "value": "contract"}]
assert await channel.send({"event": "message", "value": "contract"}) is None
assert await channel.unsubscribe() is None
@@ -134,3 +138,280 @@ async def scenario() -> None:
("unsubscribe", None),
]
assert received == [{"event": "message", "value": "contract"}]
+
+
+def test_realtime_callbacks_run_outside_the_message_processor() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=lambda *args, **kwargs: official,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ channel = client.realtime.channel("contract")
+ started = asyncio.Event()
+ release = asyncio.Event()
+
+ async def callback(data: Any) -> None:
+ del data
+ started.set()
+ await release.wait()
+
+ channel.on("message", callback)
+ await channel.subscribe()
+ await asyncio.wait_for(
+ official.emit_wire_publication(
+ "broadcast:contract",
+ {"event": "message"},
+ ),
+ timeout=0.1,
+ )
+ await asyncio.wait_for(started.wait(), timeout=0.1)
+ release.set()
+ await client.realtime.disconnect()
+
+ asyncio.run(scenario())
+
+
+def test_realtime_opens_one_connection_when_first_used_concurrently() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ entered = asyncio.Event()
+ release = asyncio.Event()
+ created = 0
+
+ async def connect() -> None:
+ entered.set()
+ await release.wait()
+ official.calls.append("connect")
+
+ official.connect = connect
+
+ def factory(*args: Any, **kwargs: Any) -> FakeCentrifugeClient:
+ nonlocal created
+ del args, kwargs
+ created += 1
+ return official
+
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=factory,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ first = asyncio.create_task(client.realtime._connect())
+ await entered.wait()
+ second = asyncio.create_task(client.realtime._connect())
+ await asyncio.sleep(0)
+ release.set()
+ assert await first is await second
+ assert created == 1
+ await client.realtime.disconnect()
+
+ asyncio.run(scenario())
+
+
+def test_realtime_callback_failure_does_not_stop_later_callbacks() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=lambda *args, **kwargs: official,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ channel = client.realtime.channel("contract")
+ received: list[str] = []
+ errors: list[dict[str, Any]] = []
+ loop = asyncio.get_running_loop()
+ previous_handler = loop.get_exception_handler()
+ loop.set_exception_handler(lambda _loop, context: errors.append(context))
+
+ def callback(data: dict[str, str]) -> None:
+ if data["value"] == "first":
+ raise RuntimeError("callback failed")
+ received.append(data["value"])
+
+ try:
+ channel.on("message", callback)
+ await channel.subscribe()
+ await official.emit_wire_publication(
+ "broadcast:contract",
+ {"event": "message", "value": "first"},
+ )
+ await official.emit_wire_publication(
+ "broadcast:contract",
+ {"event": "message", "value": "second"},
+ )
+ for _ in range(10):
+ if received:
+ break
+ await asyncio.sleep(0)
+ assert received == ["second"]
+ assert len(errors) == 1
+ assert isinstance(errors[0].get("exception"), RuntimeError)
+ finally:
+ loop.set_exception_handler(previous_handler)
+ await client.realtime.disconnect()
+
+ asyncio.run(scenario())
+
+
+def test_realtime_callback_can_disconnect_its_own_client() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=lambda *args, **kwargs: official,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ channel = client.realtime.channel("contract")
+ disconnected = asyncio.Event()
+
+ async def callback(data: dict[str, str]) -> None:
+ if data["value"] == "first":
+ await client.realtime.disconnect()
+ await channel.subscribe()
+ await official.emit_wire_publication(
+ "broadcast:contract", {"event": "message", "value": "second"}
+ )
+ else:
+ disconnected.set()
+
+ channel.on("message", callback)
+ await channel.subscribe()
+ await official.emit_wire_publication(
+ "broadcast:contract", {"event": "message", "value": "first"}
+ )
+ await asyncio.wait_for(disconnected.wait(), timeout=0.1)
+ await client.realtime.disconnect()
+
+ asyncio.run(scenario())
+ assert official.calls == [
+ "connect",
+ "channel:broadcast:contract",
+ "disconnect",
+ "connect",
+ "channel:broadcast:contract",
+ "disconnect",
+ ]
+
+
+def test_realtime_disconnect_excludes_a_concurrent_first_connect() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ entered = asyncio.Event()
+ release = asyncio.Event()
+
+ async def connect() -> None:
+ entered.set()
+ await release.wait()
+ official.calls.append("connect")
+
+ official.connect = connect
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=lambda *args, **kwargs: official,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ channel = client.realtime.channel("contract")
+ subscribing = asyncio.create_task(channel.subscribe())
+ await entered.wait()
+ disconnecting = asyncio.create_task(client.realtime.disconnect())
+ await asyncio.sleep(0)
+ release.set()
+ await subscribing
+ await disconnecting
+ assert channel._subscription is None
+
+ asyncio.run(scenario())
+ assert official.calls == ["connect", "channel:broadcast:contract", "disconnect"]
+
+
+def test_realtime_disconnect_excludes_subscription_on_an_existing_connection() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ entered = asyncio.Event()
+ release = asyncio.Event()
+
+ class BlockingSubscription(FakeSubscription):
+ async def subscribe(self) -> None:
+ entered.set()
+ await release.wait()
+ await super().subscribe()
+
+ def new_subscription(name: str, *, events: Any) -> FakeSubscription:
+ official.calls.append(f"channel:{name}")
+ official.subscription = BlockingSubscription(events)
+ official._subs[name] = official.subscription
+ return official.subscription
+
+ official.new_subscription = new_subscription
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=lambda *args, **kwargs: official,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ await client.realtime._connect()
+ channel = client.realtime.channel("contract")
+ subscribing = asyncio.create_task(channel.subscribe())
+ await entered.wait()
+ disconnecting = asyncio.create_task(client.realtime.disconnect())
+ await asyncio.sleep(0)
+ assert "disconnect" not in official.calls
+ release.set()
+ await subscribing
+ await disconnecting
+ assert channel._subscription is None
+
+ asyncio.run(scenario())
+ assert official.calls == ["connect", "channel:broadcast:contract", "disconnect"]
+
+
+def test_realtime_disconnect_snapshots_channels_before_resetting() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=lambda *args, **kwargs: official,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ first = client.realtime.channel("first")
+ await first.subscribe()
+ entered = asyncio.Event()
+ release = asyncio.Event()
+ original_reset = first._reset
+
+ async def blocking_reset() -> None:
+ entered.set()
+ await release.wait()
+ await original_reset()
+
+ first._reset = blocking_reset
+ disconnecting = asyncio.create_task(client.realtime.disconnect())
+ await entered.wait()
+ second = client.realtime.channel("second")
+ release.set()
+ await disconnecting
+ assert second._subscription is None
+
+ asyncio.run(scenario())
From 60078306f3b3962b73154d03d15af500b3c969dc Mon Sep 17 00:00:00 2001
From: Sean Keever <33592180+swkeever@users.noreply.github.com>
Date: Thu, 27 Aug 2026 12:13:39 -0400
Subject: [PATCH 4/6] fix(realtime): disambiguate channel routing
---
src/volcano_sdk/realtime.py | 10 ++++++----
tests/unit/test_realtime.py | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/src/volcano_sdk/realtime.py b/src/volcano_sdk/realtime.py
index 327eb501..80917175 100644
--- a/src/volcano_sdk/realtime.py
+++ b/src/volcano_sdk/realtime.py
@@ -85,10 +85,12 @@ def get(self, key: str, default: Any = None) -> Any:
subscription = super().get(key)
if subscription is not None:
return subscription
- for channel, candidate in self.items():
- if key.endswith(f":{channel}"):
- return candidate
- return default
+ matches = [
+ (channel, candidate)
+ for channel, candidate in self.items()
+ if key.endswith(f":{channel}")
+ ]
+ return max(matches, key=lambda match: len(match[0]))[1] if matches else default
class _VolcanoCentrifugeConnection:
diff --git a/tests/unit/test_realtime.py b/tests/unit/test_realtime.py
index f83d4af8..e67e1796 100644
--- a/tests/unit/test_realtime.py
+++ b/tests/unit/test_realtime.py
@@ -176,6 +176,40 @@ async def callback(data: Any) -> None:
asyncio.run(scenario())
+def test_realtime_routes_overlapping_channel_suffixes_to_the_longest_match() -> None:
+ transport = AuthTransport()
+ official = FakeCentrifugeClient()
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=lambda *args, **kwargs: official,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ received: list[str] = []
+ short = client.realtime.channel("foo").on(
+ "message", lambda _data: received.append("short")
+ )
+ long = client.realtime.channel("x:broadcast:foo").on(
+ "message", lambda _data: received.append("long")
+ )
+ await short.subscribe()
+ await long.subscribe()
+ await official.emit_wire_publication(
+ "project-id:broadcast:x:broadcast:foo",
+ {"event": "message"},
+ )
+ for _ in range(10):
+ if received:
+ break
+ await asyncio.sleep(0)
+ assert received == ["long"]
+ await client.realtime.disconnect()
+
+ asyncio.run(scenario())
+
+
def test_realtime_opens_one_connection_when_first_used_concurrently() -> None:
transport = AuthTransport()
official = FakeCentrifugeClient()
From 24e2fe4821cef4ee8d3f6251f63bc3bf342243ee Mon Sep 17 00:00:00 2001
From: Sean Keever <33592180+swkeever@users.noreply.github.com>
Date: Thu, 27 Aug 2026 16:18:49 -0400
Subject: [PATCH 5/6] chore: enforce strict Python quality gates
---
.github/workflows/ci.yml | 2 +
README.md | 10 +-
features/contract_support.py | 51 ++++++---
features/environment.py | 16 ++-
features/steps/sdk_contract_steps.py | 13 ++-
pyproject.toml | 64 ++++++++++-
scripts/check_openapi.py | 5 +
scripts/generate_openapi.py | 9 +-
src/volcano_sdk/__init__.py | 2 +
src/volcano_sdk/_transport.py | 92 +++++++++++-----
src/volcano_sdk/auth.py | 8 ++
src/volcano_sdk/client.py | 18 +++-
src/volcano_sdk/database.py | 14 ++-
src/volcano_sdk/errors.py | 19 ++--
src/volcano_sdk/locks.py | 13 ++-
src/volcano_sdk/models.py | 11 +-
src/volcano_sdk/realtime.py | 91 +++++++++++++---
src/volcano_sdk/storage.py | 12 +++
tests/unit/test_contract_bindings.py | 31 ++++--
tests/unit/test_errors.py | 68 +++++++++++-
tests/unit/test_facade.py | 12 +--
tests/unit/test_generated_transport.py | 3 +-
tests/unit/test_generation.py | 11 +-
tests/unit/test_import.py | 5 +-
tests/unit/test_realtime.py | 140 ++++++++++++++++++++-----
uv.lock | 24 +++++
26 files changed, 597 insertions(+), 147 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 34c823fc..4f4061b9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,7 +21,9 @@ jobs:
- run: uv sync --frozen
- run: uv run python scripts/check_openapi.py
- run: uv run ruff check .
+ - run: uv run ruff format --check .
- run: uv run mypy
+ - run: uv run pyright
- run: uv run pytest tests/unit -q
- name: Check contract feature bindings
run: |
diff --git a/README.md b/README.md
index 8fbe5187..3fc86884 100644
--- a/README.md
+++ b/README.md
@@ -19,13 +19,7 @@ client = VolcanoClient(
session = client.auth.sign_in(email="user@example.com", password="secret")
-rows = (
- client.database("main")
- .from_("items")
- .select("*")
- .eq("slug", "a")
- .execute()
-)
+rows = client.database("main").from_("items").select("*").eq("slug", "a").execute()
bucket = client.storage.from_("assets")
bucket.upload("a.txt", b"hello")
@@ -67,7 +61,9 @@ subscription, publish, and disconnect behavior to `centrifuge-python` 0.6.
uv sync --frozen
uv run python scripts/check_openapi.py
uv run ruff check .
+uv run ruff format --check .
uv run mypy
+uv run pyright
uv run pytest tests/unit -q
uv run python -m build
```
diff --git a/features/contract_support.py b/features/contract_support.py
index e77c1465..fc626414 100644
--- a/features/contract_support.py
+++ b/features/contract_support.py
@@ -3,9 +3,8 @@
import asyncio
import os
import secrets
-from collections.abc import Awaitable, Callable
from dataclasses import dataclass
-from typing import Any
+from typing import TYPE_CHECKING, Any
from centrifuge import CentrifugeError
@@ -20,8 +19,18 @@
VolcanoClient,
VolcanoError,
)
-from volcano_sdk.models import LockLease
-from volcano_sdk.realtime import Channel
+
+if TYPE_CHECKING:
+ from collections.abc import Awaitable, Callable
+
+ from volcano_sdk.models import LockLease
+ from volcano_sdk.realtime import Channel
+
+HTTP_NOT_FOUND = 404
+HTTP_CONFLICT = 409
+HTTP_RATE_LIMITED = 429
+HTTP_SERVER_ERROR_MIN = 500
+HTTP_SERVER_ERROR_MAX = 599
CONTRACT_EXCEPTIONS = (
CentrifugeError,
@@ -52,22 +61,33 @@ def classify_error(error: Exception) -> str:
(ServerError, "server error"),
(TransportError, "transport error"),
)
- for error_type, category in categories:
- if isinstance(error, error_type):
- return category
+ matched_category = next(
+ (
+ category
+ for error_type, category in categories
+ if isinstance(error, error_type)
+ ),
+ None,
+ )
+ if matched_category is not None:
+ return matched_category
if isinstance(error, VolcanoError):
status = error.status
if status in (401, 403):
return "authentication error"
if status in (400, 422):
return "validation error"
- if status == 404:
- return "not found"
- if status == 409:
- return "conflict"
- if status == 429:
- return "rate limited"
- if status is not None and 500 <= status <= 599:
+ category_by_status = {
+ HTTP_NOT_FOUND: "not found",
+ HTTP_CONFLICT: "conflict",
+ HTTP_RATE_LIMITED: "rate limited",
+ }
+ if status in category_by_status:
+ return category_by_status[status]
+ if (
+ status is not None
+ and HTTP_SERVER_ERROR_MIN <= status <= HTTP_SERVER_ERROR_MAX
+ ):
return "server error"
return "transport error"
@@ -143,4 +163,5 @@ def cleanup(self) -> None:
self.realtime_clients.clear()
self.loop.close()
if failures:
- raise ExceptionGroup("Python contract cleanup failed", failures)
+ message = "Python contract cleanup failed"
+ raise ExceptionGroup(message, failures)
diff --git a/features/environment.py b/features/environment.py
index af22ef3c..39a26b73 100644
--- a/features/environment.py
+++ b/features/environment.py
@@ -8,23 +8,29 @@
from contract_support import ContractWorld
+FIXTURE_MODE = 0o600
+FIXTURE_ABSOLUTE_PATH_ERROR = "VOLCANO_SDK_CONTRACT_FIXTURE must be an absolute path"
+FIXTURE_MODE_ERROR = "VOLCANO_SDK_CONTRACT_FIXTURE must have mode 0600"
+FIXTURE_OBJECT_ERROR = "VOLCANO_SDK_CONTRACT_FIXTURE must contain a JSON object"
+FIXTURE_REQUIRED_ERROR = "VOLCANO_SDK_CONTRACT_FIXTURE is required"
+
def load_fixture(path: Path) -> dict[str, Any]:
if not path.is_absolute():
- raise ValueError("VOLCANO_SDK_CONTRACT_FIXTURE must be an absolute path")
+ raise ValueError(FIXTURE_ABSOLUTE_PATH_ERROR)
mode = stat.S_IMODE(path.stat().st_mode)
- if mode != 0o600:
- raise PermissionError("VOLCANO_SDK_CONTRACT_FIXTURE must have mode 0600")
+ if mode != FIXTURE_MODE:
+ raise PermissionError(FIXTURE_MODE_ERROR)
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
- raise TypeError("VOLCANO_SDK_CONTRACT_FIXTURE must contain a JSON object")
+ raise TypeError(FIXTURE_OBJECT_ERROR)
return value
def before_all(context: Any) -> None:
fixture_path = os.environ.get("VOLCANO_SDK_CONTRACT_FIXTURE")
if fixture_path is None:
- raise RuntimeError("VOLCANO_SDK_CONTRACT_FIXTURE is required")
+ raise RuntimeError(FIXTURE_REQUIRED_ERROR)
context.contract_fixture = load_fixture(Path(fixture_path))
diff --git a/features/steps/sdk_contract_steps.py b/features/steps/sdk_contract_steps.py
index 6eb76062..60d99ef4 100644
--- a/features/steps/sdk_contract_steps.py
+++ b/features/steps/sdk_contract_steps.py
@@ -66,11 +66,13 @@ def authenticated_client(context: Any) -> None:
def select_fixture_row(context: Any) -> None:
world = _world(context)
world.record(
- lambda: world.client.database(world.fixture["database_name"])
- .from_(world.fixture["table_name"])
- .select("*")
- .eq("slug", world.fixture["fixture_row"]["slug"])
- .execute()
+ lambda: (
+ world.client.database(world.fixture["database_name"])
+ .from_(world.fixture["table_name"])
+ .select("*")
+ .eq("slug", world.fixture["fixture_row"]["slug"])
+ .execute()
+ )
)
@@ -160,6 +162,7 @@ def two_realtime_clients(context: Any) -> None:
world.realtime_clients = clients
world.subscriber = clients[0].realtime.channel(world.realtime_channel)
world.publisher = clients[1].realtime.channel(world.realtime_channel)
+
async def subscribe() -> None:
await asyncio.gather(
world.subscriber.subscribe(),
diff --git a/pyproject.toml b/pyproject.toml
index fdd8bf16..b39884e7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -32,20 +32,80 @@ dev = [
"build>=1.5.0,<2.0.0",
"mypy>=1.18.0",
"openapi-python-client==0.29.0",
+ "pyright>=1.1.405",
"pytest>=8.3.0",
"ruff>=0.9.0",
"types-python-dateutil>=2.9.0.20250822",
]
[tool.mypy]
-files = ["src"]
+files = ["src", "tests/unit", "scripts"]
python_version = "3.11"
strict = true
exclude = ["src/volcano_sdk/_generated/"]
+[[tool.mypy.overrides]]
+module = ["behave.*"]
+ignore_missing_imports = true
+
+[tool.pyright]
+include = ["src", "tests/unit", "scripts"]
+exclude = ["src/volcano_sdk/_generated"]
+pythonVersion = "3.11"
+venvPath = "."
+venv = ".venv"
+typeCheckingMode = "strict"
+# Package-level collaborators intentionally share private implementation details;
+# Ruff still enforces private access everywhere else.
+reportPrivateUsage = false
+
[tool.ruff]
target-version = "py311"
extend-exclude = ["src/volcano_sdk/_generated"]
[tool.ruff.lint]
-extend-select = ["I"]
+select = ["ALL"]
+ignore = [
+ # The repository license covers source files without per-file headers.
+ "CPY001",
+ # Ruff format uses the opposite convention or supersedes these rules.
+ "COM812",
+ "COM819",
+ "D203",
+ "D206",
+ "D213",
+ "D300",
+ "E111",
+ "E114",
+ "E117",
+ "ISC001",
+ "ISC002",
+ "Q000",
+ "Q001",
+ "Q002",
+ "Q003",
+ "W191",
+]
+
+[tool.ruff.lint.per-file-ignores]
+"features/**/*.py" = ["ANN401", "D", "INP001", "S101"]
+"scripts/*.py" = ["T201"]
+"src/volcano_sdk/_transport.py" = ["ANN401"]
+"src/volcano_sdk/auth.py" = ["SLF001"]
+"src/volcano_sdk/database.py" = ["SLF001"]
+"src/volcano_sdk/locks.py" = ["SLF001"]
+"src/volcano_sdk/realtime.py" = ["ANN401", "SLF001"]
+"src/volcano_sdk/storage.py" = ["SLF001"]
+"tests/**/*.py" = [
+ "ANN401",
+ "D",
+ "INP001",
+ "PLR2004",
+ "S101",
+ "S105",
+ "S106",
+ "SLF001",
+]
+
+[tool.pytest.ini_options]
+filterwarnings = ["error"]
diff --git a/scripts/check_openapi.py b/scripts/check_openapi.py
index 69a306ff..1a17cc90 100755
--- a/scripts/check_openapi.py
+++ b/scripts/check_openapi.py
@@ -1,4 +1,6 @@
#!/usr/bin/env python3
+"""Verify that the checked-in OpenAPI client matches regeneration."""
+
from __future__ import annotations
import sys
@@ -9,6 +11,7 @@
def generated_files(root: Path) -> dict[Path, Path]:
+ """Return generated files keyed by their path relative to the output root."""
return {
path.relative_to(root): path
for path in root.rglob("*")
@@ -19,6 +22,7 @@ def generated_files(root: Path) -> dict[Path, Path]:
def compared_files(left: Path, right: Path) -> tuple[list[str], list[str], list[str]]:
+ """Return missing, extra, and changed paths between two generated trees."""
left_files = generated_files(left)
right_files = generated_files(right)
missing = [str(path) for path in sorted(left_files.keys() - right_files.keys())]
@@ -32,6 +36,7 @@ def compared_files(left: Path, right: Path) -> tuple[list[str], list[str], list[
def main() -> None:
+ """Regenerate the client and report any checked-in drift."""
with tempfile.TemporaryDirectory(prefix="volcano-sdk-openapi-") as directory:
generated = Path(directory) / "_generated"
generate(generated)
diff --git a/scripts/generate_openapi.py b/scripts/generate_openapi.py
index 5a41bd53..dad6d92b 100755
--- a/scripts/generate_openapi.py
+++ b/scripts/generate_openapi.py
@@ -1,4 +1,6 @@
#!/usr/bin/env python3
+"""Generate the internal Python client from the bundled OpenAPI document."""
+
from __future__ import annotations
import argparse
@@ -22,10 +24,11 @@
def generate(output: Path) -> None:
+ """Generate the OpenAPI client into ``output`` and validate required operations."""
if output.exists():
shutil.rmtree(output)
output.parent.mkdir(parents=True, exist_ok=True)
- subprocess.run(
+ subprocess.run( # noqa: S603 - argv and executable are controlled by this script.
[
sys.executable,
"-m",
@@ -47,10 +50,12 @@ def generate(output: Path) -> None:
generated_operations = {path.name for path in (output / "api").rglob("*.py")}
missing = REQUIRED_OPERATION_MODULES - generated_operations
if missing:
- raise RuntimeError(f"required OpenAPI operations were not generated: {sorted(missing)}")
+ message = f"required OpenAPI operations were not generated: {sorted(missing)}"
+ raise RuntimeError(message)
def main() -> None:
+ """Parse command-line options and generate the internal client."""
parser = argparse.ArgumentParser(description="Generate the internal OpenAPI client")
parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
args = parser.parse_args()
diff --git a/src/volcano_sdk/__init__.py b/src/volcano_sdk/__init__.py
index 2b519c4c..ab9a77cb 100644
--- a/src/volcano_sdk/__init__.py
+++ b/src/volcano_sdk/__init__.py
@@ -1,3 +1,5 @@
+"""Public Volcano SDK facade."""
+
from .client import VolcanoClient
from .errors import (
AuthenticationError,
diff --git a/src/volcano_sdk/_transport.py b/src/volcano_sdk/_transport.py
index 99b100ef..d46bfb50 100644
--- a/src/volcano_sdk/_transport.py
+++ b/src/volcano_sdk/_transport.py
@@ -1,11 +1,12 @@
+"""Internal transport boundary around the generated OpenAPI client."""
+
from __future__ import annotations
import json
-from collections.abc import Callable, Mapping
from dataclasses import dataclass
from io import BytesIO
from pathlib import PurePosixPath
-from typing import Any, Protocol, cast
+from typing import TYPE_CHECKING, Any, Protocol, cast
from uuid import UUID, uuid4
import httpx
@@ -36,9 +37,41 @@
VolcanoError,
)
+if TYPE_CHECKING:
+ from collections.abc import Callable, Mapping
+
+HTTP_NOT_FOUND = 404
+HTTP_CONFLICT = 409
+HTTP_RATE_LIMITED = 429
+HTTP_SERVER_ERROR_MIN = 500
+HTTP_SERVER_ERROR_MAX = 599
+ERROR_TYPES_BY_STATUS: dict[int, type[VolcanoError]] = {
+ 400: ValidationError,
+ 401: AuthenticationError,
+ 403: AuthenticationError,
+ HTTP_NOT_FOUND: NotFoundError,
+ HTTP_CONFLICT: ConflictError,
+ 422: ValidationError,
+ HTTP_RATE_LIMITED: RateLimitedError,
+}
+
+
+class TransportResponse(Protocol):
+ @property
+ def status_code(self) -> int: ...
+
+ @property
+ def payload(self) -> Any: ...
+
+ @property
+ def content(self) -> bytes: ...
+
+ @property
+ def headers(self) -> Mapping[str, str] | None: ...
+
@dataclass(frozen=True, slots=True)
-class TransportResponse:
+class _GeneratedTransportResponse:
status_code: int
payload: Any
content: bytes
@@ -113,36 +146,39 @@ def _header(headers: Mapping[str, str] | None, name: str) -> str | None:
return None
+def _error_type(status: int) -> type[VolcanoError]:
+ error_type = ERROR_TYPES_BY_STATUS.get(status)
+ if error_type is not None:
+ return error_type
+ if HTTP_SERVER_ERROR_MIN <= status <= HTTP_SERVER_ERROR_MAX:
+ return ServerError
+ return VolcanoError
+
+
def response_payload(response: Any, expected_status: int) -> Any:
status = int(response.status_code)
if status != expected_status:
- payload = response.payload if isinstance(response.payload, dict) else {}
- message = str(payload.get("error") or payload.get("message") or "Volcano request failed")
+ payload: Mapping[str, object]
+ raw_payload = response.payload
+ if isinstance(raw_payload, dict):
+ payload = cast("Mapping[str, object]", raw_payload)
+ else:
+ payload = {}
+ message = str(
+ payload.get("error") or payload.get("message") or "Volcano request failed"
+ )
code_value = payload.get("code")
code = str(code_value) if code_value is not None else None
retry_after = None
- if status == 429:
+ if status == HTTP_RATE_LIMITED:
retry_after_value = _header(response.headers, "Retry-After")
try:
- retry_after = int(retry_after_value) if retry_after_value is not None else None
+ retry_after = (
+ int(retry_after_value) if retry_after_value is not None else None
+ )
except ValueError:
retry_after = None
- error_type: type[VolcanoError]
- if status in (401, 403):
- error_type = AuthenticationError
- elif status in (400, 422):
- error_type = ValidationError
- elif status == 404:
- error_type = NotFoundError
- elif status == 409:
- error_type = ConflictError
- elif status == 429:
- error_type = RateLimitedError
- elif 500 <= status <= 599:
- error_type = ServerError
- else:
- error_type = VolcanoError
- raise error_type(
+ raise _error_type(status)(
message,
status=status,
code=code,
@@ -186,7 +222,7 @@ def _response(response: Any) -> TransportResponse:
payload = json.loads(response.content)
except (json.JSONDecodeError, UnicodeDecodeError):
payload = None
- return TransportResponse(
+ return _GeneratedTransportResponse(
status_code=int(response.status_code),
payload=payload,
content=response.content,
@@ -275,8 +311,8 @@ def acquire_project_lock(
key,
client=client,
body=ProjectLockLeaseRequest(ttl_seconds=ttl),
- x_volcano_lock_token=cast(UUID, token),
- x_volcano_request_id=cast(UUID, str(uuid4())),
+ x_volcano_lock_token=cast("UUID", token),
+ x_volcano_request_id=cast("UUID", str(uuid4())),
)
return self._response(response)
@@ -291,7 +327,7 @@ def release_project_lock(
response = release_project_lock.sync_detailed(
key,
client=client,
- x_volcano_lock_token=cast(UUID, token),
- x_volcano_request_id=cast(UUID, str(uuid4())),
+ x_volcano_lock_token=cast("UUID", token),
+ x_volcano_request_id=cast("UUID", str(uuid4())),
)
return self._response(response)
diff --git a/src/volcano_sdk/auth.py b/src/volcano_sdk/auth.py
index 821e1e29..c4dcaa7e 100644
--- a/src/volcano_sdk/auth.py
+++ b/src/volcano_sdk/auth.py
@@ -1,3 +1,5 @@
+"""Authentication facade."""
+
from __future__ import annotations
from typing import Protocol
@@ -7,6 +9,8 @@
class AuthContext(Protocol):
+ """Client capabilities required by the authentication facade."""
+
_transport: Transport
def _anon_token(self) -> str: ...
@@ -15,10 +19,14 @@ def _set_session(self, session: Session) -> None: ...
class Auth:
+ """Authenticate users and update the client session."""
+
def __init__(self, client: AuthContext) -> None:
+ """Create an authentication facade backed by a client."""
self._client = client
def sign_in(self, *, email: str, password: str) -> Session:
+ """Sign in a user and store the returned session."""
response = invoke(
self._client._transport.auth_signin,
authorization=self._client._anon_token(),
diff --git a/src/volcano_sdk/client.py b/src/volcano_sdk/client.py
index b47c6c16..33c18ad9 100644
--- a/src/volcano_sdk/client.py
+++ b/src/volcano_sdk/client.py
@@ -1,13 +1,22 @@
+"""Top-level Volcano client."""
+
from __future__ import annotations
+from typing import TYPE_CHECKING
+
from ._transport import GeneratedTransport, Transport
from .auth import Auth
from .database import Database
from .locks import Locks
-from .models import Session
from .realtime import CentrifugeFactory, Realtime
from .storage import Storage
+if TYPE_CHECKING:
+ from .models import Session
+
+_NO_ACTIVE_SESSION = "No active session"
+_NO_SERVICE_KEY = "No service key configured"
+
class VolcanoClient:
"""Volcano SDK entry point."""
@@ -22,6 +31,7 @@ def __init__(
_transport: Transport | None = None,
_realtime_client_factory: CentrifugeFactory | None = None,
) -> None:
+ """Create a client for a Volcano project."""
self._api_url = api_url.rstrip("/")
self._anon_key = anon_key
self._service_key = service_key
@@ -45,9 +55,11 @@ def __init__(
@property
def current_session(self) -> Session | None:
+ """Return the authenticated session, if one exists."""
return self._current_session
def database(self, name: str) -> Database:
+ """Create a query facade for a project database."""
return Database(self, name)
def _anon_token(self) -> str:
@@ -55,12 +67,12 @@ def _anon_token(self) -> str:
def _session_token(self) -> str:
if self._current_session is None:
- raise RuntimeError("No active session")
+ raise RuntimeError(_NO_ACTIVE_SESSION)
return self._current_session.access_token
def _service_token(self) -> str:
if self._service_key is None:
- raise RuntimeError("No service key configured")
+ raise RuntimeError(_NO_SERVICE_KEY)
return self._service_key
def _set_session(self, session: Session) -> None:
diff --git a/src/volcano_sdk/database.py b/src/volcano_sdk/database.py
index 0db71c6c..97b6fc9a 100644
--- a/src/volcano_sdk/database.py
+++ b/src/volcano_sdk/database.py
@@ -1,3 +1,5 @@
+"""Database query facade."""
+
from __future__ import annotations
from dataclasses import dataclass, replace
@@ -7,6 +9,8 @@
class DatabaseContext(Protocol):
+ """Client capabilities required by database queries."""
+
_transport: Transport
def _session_token(self) -> str: ...
@@ -14,6 +18,8 @@ def _session_token(self) -> str: ...
@dataclass(frozen=True, slots=True)
class QueryBuilder:
+ """Build and execute an immutable database select query."""
+
_client: DatabaseContext
_database_name: str
_table: str
@@ -21,13 +27,16 @@ class QueryBuilder:
_filters: tuple[dict[str, Any], ...] = ()
def select(self, *columns: str) -> QueryBuilder:
+ """Select the requested columns."""
return replace(self, _columns=columns)
- def eq(self, column: str, value: Any) -> QueryBuilder:
+ def eq(self, column: str, value: object) -> QueryBuilder:
+ """Add an equality filter."""
condition = {"column": column, "operator": "eq", "value": value}
return replace(self, _filters=(*self._filters, condition))
def execute(self) -> list[dict[str, Any]]:
+ """Execute the query and return its rows."""
body: dict[str, Any] = {"table": self._table}
if self._columns and self._columns != ("*",):
body["select"] = list(self._columns)
@@ -45,8 +54,11 @@ def execute(self) -> list[dict[str, Any]]:
@dataclass(frozen=True, slots=True)
class Database:
+ """Entry point for queries against one database."""
+
_client: DatabaseContext
_name: str
def from_(self, table: str) -> QueryBuilder:
+ """Create a query builder for a table."""
return QueryBuilder(self._client, self._name, table)
diff --git a/src/volcano_sdk/errors.py b/src/volcano_sdk/errors.py
index e5aa819e..ae97c6ed 100644
--- a/src/volcano_sdk/errors.py
+++ b/src/volcano_sdk/errors.py
@@ -1,7 +1,11 @@
+"""Typed errors raised by the Volcano SDK."""
+
from __future__ import annotations
class VolcanoError(Exception):
+ """Base error containing structured Volcano response details."""
+
def __init__(
self,
message: str,
@@ -10,6 +14,7 @@ def __init__(
code: str | None = None,
retry_after: int | None = None,
) -> None:
+ """Create an error from an API or transport failure."""
super().__init__(message)
self.status = status
self.code = code
@@ -17,28 +22,28 @@ def __init__(
class AuthenticationError(VolcanoError):
- pass
+ """The supplied credentials are missing or invalid."""
class ValidationError(VolcanoError):
- pass
+ """The request failed API validation."""
class NotFoundError(VolcanoError):
- pass
+ """The requested resource does not exist."""
class ConflictError(VolcanoError):
- pass
+ """The request conflicts with the current resource state."""
class RateLimitedError(VolcanoError):
- pass
+ """The API rejected the request because of a rate limit."""
class ServerError(VolcanoError):
- pass
+ """The Volcano API failed to process the request."""
class TransportError(VolcanoError):
- pass
+ """The request failed before receiving an API response."""
diff --git a/src/volcano_sdk/locks.py b/src/volcano_sdk/locks.py
index 44c2fb8c..8058ea86 100644
--- a/src/volcano_sdk/locks.py
+++ b/src/volcano_sdk/locks.py
@@ -1,7 +1,9 @@
+"""Distributed lock facade."""
+
from __future__ import annotations
from datetime import datetime
-from typing import Any, Protocol
+from typing import Protocol
from uuid import uuid4
from ._transport import Transport, invoke, response_payload
@@ -9,22 +11,28 @@
class LocksContext(Protocol):
+ """Client capabilities required by distributed locks."""
+
_transport: Transport
def _service_token(self) -> str: ...
-def _parse_datetime(value: Any) -> datetime | None:
+def _parse_datetime(value: object) -> datetime | None:
if value is None:
return None
return datetime.fromisoformat(str(value))
class Locks:
+ """Acquire and release project-scoped distributed locks."""
+
def __init__(self, client: LocksContext) -> None:
+ """Create a lock facade backed by a client."""
self._client = client
def acquire(self, key: str, *, ttl: int) -> LockLease:
+ """Acquire a lock lease for the requested number of seconds."""
token = str(uuid4())
response = invoke(
self._client._transport.acquire_project_lock,
@@ -42,6 +50,7 @@ def acquire(self, key: str, *, ttl: int) -> LockLease:
)
def release(self, key: str, lease: LockLease) -> None:
+ """Release a lock lease."""
response = invoke(
self._client._transport.release_project_lock,
authorization=self._client._service_token(),
diff --git a/src/volcano_sdk/models.py b/src/volcano_sdk/models.py
index 3bfd7462..8ff7275b 100644
--- a/src/volcano_sdk/models.py
+++ b/src/volcano_sdk/models.py
@@ -1,11 +1,18 @@
+"""Public Volcano SDK value objects."""
+
from __future__ import annotations
from dataclasses import dataclass
-from datetime import datetime
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from datetime import datetime
@dataclass(frozen=True, slots=True)
class Session:
+ """Authenticated user session."""
+
access_token: str
refresh_token: str
user_id: str
@@ -13,6 +20,8 @@ class Session:
@dataclass(frozen=True, slots=True)
class LockLease:
+ """Lease returned for an acquired distributed lock."""
+
key: str
token: str
expires_at: datetime | None
diff --git a/src/volcano_sdk/realtime.py b/src/volcano_sdk/realtime.py
index 80917175..ab6a552c 100644
--- a/src/volcano_sdk/realtime.py
+++ b/src/volcano_sdk/realtime.py
@@ -1,3 +1,5 @@
+"""Realtime broadcast facade."""
+
from __future__ import annotations
import asyncio
@@ -9,60 +11,97 @@
MessageCallback = Callable[[Any], Any]
CALLBACK_QUEUE_LIMIT = 128
+CALLBACK_QUEUE_FULL_MESSAGE = (
+ "Volcano realtime callback queue is full; publication dropped"
+)
+CHANNEL_NOT_SUBSCRIBED = "Channel must be subscribed before sending"
+SUBSCRIPTION_REGISTRY_UNAVAILABLE = (
+ "centrifuge client subscription registry is unavailable"
+)
class RealtimeContext(Protocol):
+ """Client capabilities required by realtime connections."""
+
def _anon_token(self) -> str: ...
def _session_token(self) -> str: ...
class CentrifugeSubscription(Protocol):
- async def subscribe(self) -> None: ...
+ """Centrifuge subscription operations used by the SDK."""
+
+ async def subscribe(self) -> None:
+ """Subscribe to the remote channel."""
+ ...
- async def publish(self, data: Any) -> Any: ...
+ async def publish(self, data: Any) -> Any:
+ """Publish a payload to the remote channel."""
+ ...
- async def unsubscribe(self) -> None: ...
+ async def unsubscribe(self) -> None:
+ """Unsubscribe from the remote channel."""
+ ...
class CentrifugeConnection(Protocol):
- async def connect(self) -> None: ...
+ """Centrifuge connection operations used by the SDK."""
+
+ async def connect(self) -> None:
+ """Open the remote connection."""
+ ...
- async def disconnect(self) -> None: ...
+ async def disconnect(self) -> None:
+ """Close the remote connection."""
+ ...
def new_subscription(
self,
name: str,
*,
events: Any,
- ) -> CentrifugeSubscription: ...
+ ) -> CentrifugeSubscription:
+ """Create a subscription for a remote channel."""
+ ...
class CentrifugeFactory(Protocol):
+ """Construct a typed Centrifuge connection."""
+
def __call__(
self,
address: str,
*,
token: str,
get_token: Callable[[], Awaitable[str]],
- ) -> CentrifugeConnection: ...
+ ) -> CentrifugeConnection:
+ """Construct a Centrifuge connection."""
+ ...
class CentrifugeConstructor(Protocol):
+ """Describe the dynamically imported Centrifuge client constructor."""
+
def __call__(
self,
address: str,
*,
token: str,
get_token: Callable[[], Awaitable[str]],
- ) -> object: ...
+ ) -> object:
+ """Construct the dynamically imported Centrifuge client."""
+ ...
class Publication(Protocol):
+ """Publication payload received from Centrifuge."""
+
data: Any
class PublicationContext(Protocol):
+ """Centrifuge callback context containing a publication."""
+
pub: Publication
@@ -73,9 +112,9 @@ def _centrifuge_client(
get_token: Callable[[], Awaitable[str]],
) -> CentrifugeConnection:
module = importlib.import_module("centrifuge")
- constructor = cast(CentrifugeConstructor, module.Client)
+ constructor = cast("CentrifugeConstructor", module.Client)
return cast(
- CentrifugeConnection,
+ "CentrifugeConnection",
constructor(address, token=token, get_token=get_token),
)
@@ -99,8 +138,9 @@ def __init__(self, connection: CentrifugeConnection) -> None:
state = vars(connection)
subscriptions = state.get("_subs")
if not isinstance(subscriptions, dict):
- raise TypeError("centrifuge client subscription registry is unavailable")
- state["_subs"] = _ProjectAwareSubscriptions(subscriptions)
+ raise TypeError(SUBSCRIPTION_REGISTRY_UNAVAILABLE)
+ typed_subscriptions = cast("dict[str, Any]", subscriptions)
+ state["_subs"] = _ProjectAwareSubscriptions(typed_subscriptions)
async def connect(self) -> None:
await self._connection.connect()
@@ -144,7 +184,10 @@ async def on_error(self, ctx: Any) -> None:
class Channel:
+ """Realtime broadcast channel."""
+
def __init__(self, realtime: Realtime, name: str) -> None:
+ """Create a channel managed by a realtime facade."""
self._realtime = realtime
self._name = name
self._message_callbacks: list[MessageCallback] = []
@@ -157,18 +200,23 @@ def __init__(self, realtime: Realtime, name: str) -> None:
self._callback_stop: asyncio.Event | None = None
def on(self, event: str, callback: MessageCallback) -> Channel:
+ """Register a callback for broadcast messages."""
if event != "message":
- raise ValueError(f"unsupported realtime event: {event}")
+ message = f"unsupported realtime event: {event}"
+ raise ValueError(message)
self._message_callbacks.append(callback)
return self
async def subscribe(self) -> None:
+ """Subscribe to this channel."""
await self._realtime._subscribe(self)
async def send(self, data: Any) -> None:
+ """Publish a broadcast payload to this channel."""
await self._realtime._publish(self, data)
async def unsubscribe(self) -> None:
+ """Unsubscribe from this channel."""
await self._realtime._unsubscribe(self)
async def _emit(self, data: Any) -> None:
@@ -176,14 +224,16 @@ async def _emit(self, data: Any) -> None:
if task is None or task.done():
self._start_callback_dispatcher()
elif self._callback_stop is not None and self._callback_stop.is_set():
- self._callback_task = asyncio.create_task(self._restart_callback_dispatcher(task))
+ self._callback_task = asyncio.create_task(
+ self._restart_callback_dispatcher(task)
+ )
self._callback_stop = None
try:
self._callback_queue.put_nowait(data)
except asyncio.QueueFull:
asyncio.get_running_loop().call_exception_handler(
{
- "message": "Volcano realtime callback queue is full; publication dropped",
+ "message": CALLBACK_QUEUE_FULL_MESSAGE,
"channel": self._name,
}
)
@@ -204,7 +254,9 @@ async def _dispatch_callbacks(self, stop: asyncio.Event) -> None:
data = await self._callback_queue.get()
try:
for callback in tuple(self._message_callbacks):
- active_task = asyncio.create_task(self._run_callback(callback, data))
+ active_task = asyncio.create_task(
+ self._run_callback(callback, data)
+ )
self._active_callback_task = active_task
try:
(error,) = await asyncio.gather(
@@ -246,6 +298,8 @@ async def _reset(self) -> None:
class Realtime:
+ """Manage project realtime connections and channels."""
+
def __init__(
self,
client: RealtimeContext,
@@ -253,6 +307,7 @@ def __init__(
api_url: str,
client_factory: CentrifugeFactory = _centrifuge_client,
) -> None:
+ """Create a lazily connected realtime facade."""
self._client_context = client
self._api_url = api_url
self._client_factory = client_factory
@@ -261,6 +316,7 @@ def __init__(
self._channels: dict[str, Channel] = {}
def channel(self, name: str) -> Channel:
+ """Return a stable channel facade for a broadcast name."""
wire_name = f"broadcast:{name}"
if wire_name not in self._channels:
self._channels[wire_name] = Channel(self, wire_name)
@@ -306,7 +362,7 @@ async def _subscribe(self, channel: Channel) -> None:
async def _publish(self, channel: Channel, data: Any) -> None:
async with self._connection_lock:
if channel._subscription is None:
- raise RuntimeError("Channel must be subscribed before sending")
+ raise RuntimeError(CHANNEL_NOT_SUBSCRIBED)
await channel._subscription.publish(data)
async def _unsubscribe(self, channel: Channel) -> None:
@@ -315,6 +371,7 @@ async def _unsubscribe(self, channel: Channel) -> None:
await channel._subscription.unsubscribe()
async def disconnect(self) -> None:
+ """Disconnect and reset every channel managed by this facade."""
async with self._connection_lock:
connection = self._connection
self._connection = None
diff --git a/src/volcano_sdk/storage.py b/src/volcano_sdk/storage.py
index 84817d6a..b89685c5 100644
--- a/src/volcano_sdk/storage.py
+++ b/src/volcano_sdk/storage.py
@@ -1,3 +1,5 @@
+"""Object storage facade."""
+
from __future__ import annotations
from dataclasses import dataclass
@@ -7,6 +9,8 @@
class StorageContext(Protocol):
+ """Client capabilities required by object storage."""
+
_transport: Transport
def _session_token(self) -> str: ...
@@ -14,10 +18,13 @@ def _session_token(self) -> str: ...
@dataclass(frozen=True, slots=True)
class StorageBucket:
+ """Operations scoped to one storage bucket."""
+
_client: StorageContext
_name: str
def upload(self, path: str, data: bytes) -> dict[str, Any]:
+ """Upload bytes to a path in this bucket."""
response = invoke(
self._client._transport.upload_storage_object,
authorization=self._client._session_token(),
@@ -29,6 +36,7 @@ def upload(self, path: str, data: bytes) -> dict[str, Any]:
return dict(payload)
def download(self, path: str) -> bytes:
+ """Download bytes from a path in this bucket."""
response = invoke(
self._client._transport.download_storage_object,
authorization=self._client._session_token(),
@@ -40,8 +48,12 @@ def download(self, path: str) -> bytes:
class Storage:
+ """Entry point for project object storage."""
+
def __init__(self, client: StorageContext) -> None:
+ """Create a storage facade backed by a client."""
self._client = client
def from_(self, bucket: str) -> StorageBucket:
+ """Create a facade scoped to a bucket."""
return StorageBucket(self._client, bucket)
diff --git a/tests/unit/test_contract_bindings.py b/tests/unit/test_contract_bindings.py
index eefb6c92..7493fb77 100644
--- a/tests/unit/test_contract_bindings.py
+++ b/tests/unit/test_contract_bindings.py
@@ -5,26 +5,37 @@
import os
import sys
from pathlib import Path
+from typing import TYPE_CHECKING
import pytest
from behave.step_registry import registry
+if TYPE_CHECKING:
+ from types import ModuleType
+
ROOT = Path(__file__).parents[2]
FEATURE_SHA256 = {
"auth.feature": "6e6bcc6244bbdb9b1c141a3f0d8f1256d2be0057429457084a094ed98cbcbd07",
- "database.feature": "4685b29357a621068b25984ff0de29cd4c504eebe5cfb597f0b999e29878a668",
+ "database.feature": (
+ "4685b29357a621068b25984ff0de29cd4c504eebe5cfb597f0b999e29878a668"
+ ),
"locks.feature": "76fa31f9a7c203e33b367e5ca1467b2334e7c85c960de8d5cab8638920137411",
- "realtime.feature": "e65862e27656cdd0afa8e552cb5a628d9831568e3299711e572ccd4f6b750696",
- "storage.feature": "0772d46691d2a158e752d19cea995ff79db960fc3774c799ebdf081e19424d82",
+ "realtime.feature": (
+ "e65862e27656cdd0afa8e552cb5a628d9831568e3299711e572ccd4f6b750696"
+ ),
+ "storage.feature": (
+ "0772d46691d2a158e752d19cea995ff79db960fc3774c799ebdf081e19424d82"
+ ),
}
-def _load_module(name: str, path: Path):
+def _load_module(name: str, path: Path) -> ModuleType:
features_path = str(ROOT / "features")
if features_path not in sys.path:
sys.path.insert(0, features_path)
spec = importlib.util.spec_from_file_location(name, path)
- assert spec is not None and spec.loader is not None
+ assert spec is not None
+ assert spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
@@ -39,7 +50,9 @@ def test_contract_features_match_shared_source() -> None:
def test_every_contract_phrase_is_bound_verbatim() -> None:
registry.clear()
- _load_module("contract_steps", ROOT / "features" / "steps" / "sdk_contract_steps.py")
+ _load_module(
+ "contract_steps", ROOT / "features" / "steps" / "sdk_contract_steps.py"
+ )
bound = {
definition.pattern
for definitions in registry.steps.values()
@@ -52,7 +65,7 @@ def test_every_contract_phrase_is_bound_verbatim() -> None:
"one client subscribes and the other publishes the contract message",
"the SDK operation succeeds",
"the client acquires and releases the contract lock",
- "the client selects the contract table where \"slug\" equals the fixture slug",
+ 'the client selects the contract table where "slug" equals the fixture slug',
"the client signs in with the contract user's credentials",
"the client uploads and downloads the contract object",
"the confirmed contract user",
@@ -67,7 +80,9 @@ def test_every_contract_phrase_is_bound_verbatim() -> None:
def test_fixture_loader_requires_absolute_private_file(tmp_path: Path) -> None:
- environment = _load_module("contract_environment", ROOT / "features" / "environment.py")
+ environment = _load_module(
+ "contract_environment", ROOT / "features" / "environment.py"
+ )
fixture = tmp_path / "fixture.json"
fixture.write_text("{}", encoding="utf-8")
diff --git a/tests/unit/test_errors.py b/tests/unit/test_errors.py
index e0008834..43c802db 100644
--- a/tests/unit/test_errors.py
+++ b/tests/unit/test_errors.py
@@ -18,6 +18,8 @@
VolcanoError,
)
+UNEXPECTED_TRANSPORT_CALL = "unexpected transport operation"
+
@dataclass(frozen=True)
class ErrorResponse:
@@ -31,12 +33,70 @@ class ErrorTransport:
def __init__(self, failure: ErrorResponse | Exception) -> None:
self.failure = failure
- def auth_signin(self, **kwargs: Any) -> ErrorResponse:
- del kwargs
+ def auth_signin(
+ self,
+ *,
+ authorization: str,
+ email: str,
+ password: str,
+ ) -> ErrorResponse:
+ del authorization, email, password
if isinstance(self.failure, Exception):
raise self.failure
return self.failure
+ def query_database_select(
+ self,
+ *,
+ authorization: str,
+ database_name: str,
+ body: dict[str, Any],
+ ) -> ErrorResponse:
+ del authorization, database_name, body
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def upload_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ data: bytes,
+ ) -> ErrorResponse:
+ del authorization, bucket_name, path, data
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def download_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ ) -> ErrorResponse:
+ del authorization, bucket_name, path
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def acquire_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ ttl: int,
+ token: str,
+ ) -> ErrorResponse:
+ del authorization, key, ttl, token
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def release_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ token: str,
+ ) -> ErrorResponse:
+ del authorization, key, token
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
@pytest.mark.parametrize(
("status", "expected"),
@@ -79,7 +139,9 @@ def test_network_failure_maps_to_transport_error() -> None:
request = httpx.Request("POST", "https://api.test.volcano.dev/auth/signin")
client = VolcanoClient(
anon_key="anon-key",
- _transport=ErrorTransport(httpx.ConnectError("connection failed", request=request)),
+ _transport=ErrorTransport(
+ httpx.ConnectError("connection failed", request=request)
+ ),
)
with pytest.raises(TransportError) as caught:
diff --git a/tests/unit/test_facade.py b/tests/unit/test_facade.py
index 3b70e52c..d11833d3 100644
--- a/tests/unit/test_facade.py
+++ b/tests/unit/test_facade.py
@@ -64,17 +64,11 @@ def test_public_facade_delegates_to_the_six_contract_operations() -> None:
)
session = client.auth.sign_in(email="user@example.com", password="secret")
- rows = (
- client.database("main")
- .from_("items")
- .select("*")
- .eq("slug", "a")
- .execute()
- )
+ rows = client.database("main").from_("items").select("*").eq("slug", "a").execute()
uploaded = client.storage.from_("assets").upload("a.txt", b"hello")
downloaded = client.storage.from_("assets").download("a.txt")
lease = client.locks.acquire("build", ttl=30)
- released = client.locks.release("build", lease)
+ client.locks.release("build", lease)
assert session == Session(
access_token="access-token",
@@ -91,8 +85,6 @@ def test_public_facade_delegates_to_the_six_contract_operations() -> None:
expires_at=datetime(2026, 8, 26, 12, 0, 30, tzinfo=UTC),
fencing_token=7,
)
- assert released is None
-
assert [name for name, _ in transport.calls] == [
"authSignin",
"queryDatabaseSelect",
diff --git a/tests/unit/test_generated_transport.py b/tests/unit/test_generated_transport.py
index 5e6ebfe6..30e5e4b3 100644
--- a/tests/unit/test_generated_transport.py
+++ b/tests/unit/test_generated_transport.py
@@ -62,7 +62,8 @@ def handle(request: httpx.Request) -> httpx.Response:
)
if request.method == "DELETE" and path == "/locks/build/lease":
return httpx.Response(204)
- raise AssertionError(f"unexpected request: {request.method} {path}")
+ message = f"unexpected request: {request.method} {path}"
+ raise AssertionError(message)
transport = GeneratedTransport(
api_url="https://api.test.volcano.dev",
diff --git a/tests/unit/test_generation.py b/tests/unit/test_generation.py
index 7fa65cc3..b226d4fc 100644
--- a/tests/unit/test_generation.py
+++ b/tests/unit/test_generation.py
@@ -1,9 +1,11 @@
import os
+import sys
from pathlib import Path
from runpy import run_path
ROOT = Path(__file__).resolve().parents[2]
+
def test_generate_emits_all_six_contract_operations(tmp_path: Path) -> None:
script = run_path(str(ROOT / "scripts" / "generate_openapi.py"))
generate = script["generate"]
@@ -22,11 +24,14 @@ def test_generate_emits_all_six_contract_operations(tmp_path: Path) -> None:
def test_generated_comparison_reads_file_bytes(
- monkeypatch: object,
tmp_path: Path,
) -> None:
- monkeypatch.syspath_prepend(str(ROOT / "scripts"))
- script = run_path(str(ROOT / "scripts" / "check_openapi.py"))
+ scripts_path = str(ROOT / "scripts")
+ sys.path.insert(0, scripts_path)
+ try:
+ script = run_path(str(ROOT / "scripts" / "check_openapi.py"))
+ finally:
+ sys.path.remove(scripts_path)
compared_files = script["compared_files"]
expected = tmp_path / "expected"
actual = tmp_path / "actual"
diff --git a/tests/unit/test_import.py b/tests/unit/test_import.py
index b2de547e..478ebd90 100644
--- a/tests/unit/test_import.py
+++ b/tests/unit/test_import.py
@@ -1,4 +1,5 @@
-def test_package_exports_client() -> None:
- from volcano_sdk import VolcanoClient
+from volcano_sdk import VolcanoClient
+
+def test_package_exports_client() -> None:
assert VolcanoClient.__name__ == "VolcanoClient"
diff --git a/tests/unit/test_realtime.py b/tests/unit/test_realtime.py
index e67e1796..82669728 100644
--- a/tests/unit/test_realtime.py
+++ b/tests/unit/test_realtime.py
@@ -1,13 +1,19 @@
from __future__ import annotations
import asyncio
-from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from types import SimpleNamespace
-from typing import Any
+from typing import TYPE_CHECKING, Any
from volcano_sdk import VolcanoClient
+if TYPE_CHECKING:
+ from collections.abc import Awaitable, Callable
+
+ import pytest
+
+UNEXPECTED_TRANSPORT_CALL = "unexpected transport operation"
+
@dataclass(frozen=True)
class Response:
@@ -21,8 +27,14 @@ class AuthTransport:
def __init__(self) -> None:
self.access_token = "access-1"
- def auth_signin(self, **kwargs: Any) -> Response:
- del kwargs
+ def auth_signin(
+ self,
+ *,
+ authorization: str,
+ email: str,
+ password: str,
+ ) -> Response:
+ del authorization, email, password
return Response(
200,
{
@@ -32,6 +44,58 @@ def auth_signin(self, **kwargs: Any) -> Response:
},
)
+ def query_database_select(
+ self,
+ *,
+ authorization: str,
+ database_name: str,
+ body: dict[str, Any],
+ ) -> Response:
+ del authorization, database_name, body
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def upload_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ data: bytes,
+ ) -> Response:
+ del authorization, bucket_name, path, data
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def download_storage_object(
+ self,
+ *,
+ authorization: str,
+ bucket_name: str,
+ path: str,
+ ) -> Response:
+ del authorization, bucket_name, path
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def acquire_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ ttl: int,
+ token: str,
+ ) -> Response:
+ del authorization, key, ttl, token
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
+ def release_project_lock(
+ self,
+ *,
+ authorization: str,
+ key: str,
+ token: str,
+ ) -> Response:
+ del authorization, key, token
+ raise AssertionError(UNEXPECTED_TRANSPORT_CALL)
+
class FakeSubscription:
def __init__(self, events: Any) -> None:
@@ -48,7 +112,9 @@ async def unsubscribe(self) -> None:
self.calls.append(("unsubscribe", None))
async def emit(self, data: Any) -> None:
- await self.events.on_publication(SimpleNamespace(pub=SimpleNamespace(data=data)))
+ await self.events.on_publication(
+ SimpleNamespace(pub=SimpleNamespace(data=data))
+ )
class FakeCentrifugeClient:
@@ -75,6 +141,21 @@ async def emit_wire_publication(self, name: str, data: Any) -> None:
await subscription.emit(data)
+@dataclass(frozen=True)
+class FakeCentrifugeFactory:
+ client: FakeCentrifugeClient
+
+ def __call__(
+ self,
+ address: str,
+ *,
+ token: str,
+ get_token: Callable[[], Awaitable[str]],
+ ) -> FakeCentrifugeClient:
+ del address, token, get_token
+ return self.client
+
+
def test_realtime_wraps_official_client_without_exposing_it() -> None:
transport = AuthTransport()
official = FakeCentrifugeClient()
@@ -105,7 +186,7 @@ def factory(
async def scenario() -> None:
channel = client.realtime.channel("contract")
assert channel.on("message", received.append) is channel
- assert await channel.subscribe() is None
+ await channel.subscribe()
assert official.subscription is not None
await official.emit_wire_publication(
"project-id:broadcast:contract",
@@ -116,13 +197,13 @@ async def scenario() -> None:
break
await asyncio.sleep(0)
assert received == [{"event": "message", "value": "contract"}]
- assert await channel.send({"event": "message", "value": "contract"}) is None
- assert await channel.unsubscribe() is None
+ await channel.send({"event": "message", "value": "contract"})
+ await channel.unsubscribe()
transport.access_token = "access-2"
client.auth.sign_in(email="user@example.com", password="secret")
assert await factory_arguments["get_token"]() == "access-2"
- assert await client.realtime.disconnect() is None
+ await client.realtime.disconnect()
asyncio.run(scenario())
@@ -146,7 +227,7 @@ def test_realtime_callbacks_run_outside_the_message_processor() -> None:
client = VolcanoClient(
anon_key="anon-key",
_transport=transport,
- _realtime_client_factory=lambda *args, **kwargs: official,
+ _realtime_client_factory=FakeCentrifugeFactory(official),
)
client.auth.sign_in(email="user@example.com", password="secret")
@@ -182,7 +263,7 @@ def test_realtime_routes_overlapping_channel_suffixes_to_the_longest_match() ->
client = VolcanoClient(
anon_key="anon-key",
_transport=transport,
- _realtime_client_factory=lambda *args, **kwargs: official,
+ _realtime_client_factory=FakeCentrifugeFactory(official),
)
client.auth.sign_in(email="user@example.com", password="secret")
@@ -210,7 +291,9 @@ async def scenario() -> None:
asyncio.run(scenario())
-def test_realtime_opens_one_connection_when_first_used_concurrently() -> None:
+def test_realtime_opens_one_connection_when_first_used_concurrently(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
transport = AuthTransport()
official = FakeCentrifugeClient()
entered = asyncio.Event()
@@ -222,7 +305,7 @@ async def connect() -> None:
await release.wait()
official.calls.append("connect")
- official.connect = connect
+ monkeypatch.setattr(official, "connect", connect)
def factory(*args: Any, **kwargs: Any) -> FakeCentrifugeClient:
nonlocal created
@@ -256,7 +339,7 @@ def test_realtime_callback_failure_does_not_stop_later_callbacks() -> None:
client = VolcanoClient(
anon_key="anon-key",
_transport=transport,
- _realtime_client_factory=lambda *args, **kwargs: official,
+ _realtime_client_factory=FakeCentrifugeFactory(official),
)
client.auth.sign_in(email="user@example.com", password="secret")
@@ -270,7 +353,8 @@ async def scenario() -> None:
def callback(data: dict[str, str]) -> None:
if data["value"] == "first":
- raise RuntimeError("callback failed")
+ message = "callback failed"
+ raise RuntimeError(message)
received.append(data["value"])
try:
@@ -304,7 +388,7 @@ def test_realtime_callback_can_disconnect_its_own_client() -> None:
client = VolcanoClient(
anon_key="anon-key",
_transport=transport,
- _realtime_client_factory=lambda *args, **kwargs: official,
+ _realtime_client_factory=FakeCentrifugeFactory(official),
)
client.auth.sign_in(email="user@example.com", password="secret")
@@ -341,7 +425,9 @@ async def callback(data: dict[str, str]) -> None:
]
-def test_realtime_disconnect_excludes_a_concurrent_first_connect() -> None:
+def test_realtime_disconnect_excludes_a_concurrent_first_connect(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
transport = AuthTransport()
official = FakeCentrifugeClient()
entered = asyncio.Event()
@@ -352,11 +438,11 @@ async def connect() -> None:
await release.wait()
official.calls.append("connect")
- official.connect = connect
+ monkeypatch.setattr(official, "connect", connect)
client = VolcanoClient(
anon_key="anon-key",
_transport=transport,
- _realtime_client_factory=lambda *args, **kwargs: official,
+ _realtime_client_factory=FakeCentrifugeFactory(official),
)
client.auth.sign_in(email="user@example.com", password="secret")
@@ -375,7 +461,9 @@ async def scenario() -> None:
assert official.calls == ["connect", "channel:broadcast:contract", "disconnect"]
-def test_realtime_disconnect_excludes_subscription_on_an_existing_connection() -> None:
+def test_realtime_disconnect_excludes_subscription_on_an_existing_connection(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
transport = AuthTransport()
official = FakeCentrifugeClient()
entered = asyncio.Event()
@@ -393,11 +481,11 @@ def new_subscription(name: str, *, events: Any) -> FakeSubscription:
official._subs[name] = official.subscription
return official.subscription
- official.new_subscription = new_subscription
+ monkeypatch.setattr(official, "new_subscription", new_subscription)
client = VolcanoClient(
anon_key="anon-key",
_transport=transport,
- _realtime_client_factory=lambda *args, **kwargs: official,
+ _realtime_client_factory=FakeCentrifugeFactory(official),
)
client.auth.sign_in(email="user@example.com", password="secret")
@@ -418,13 +506,15 @@ async def scenario() -> None:
assert official.calls == ["connect", "channel:broadcast:contract", "disconnect"]
-def test_realtime_disconnect_snapshots_channels_before_resetting() -> None:
+def test_realtime_disconnect_snapshots_channels_before_resetting(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
transport = AuthTransport()
official = FakeCentrifugeClient()
client = VolcanoClient(
anon_key="anon-key",
_transport=transport,
- _realtime_client_factory=lambda *args, **kwargs: official,
+ _realtime_client_factory=FakeCentrifugeFactory(official),
)
client.auth.sign_in(email="user@example.com", password="secret")
@@ -440,7 +530,7 @@ async def blocking_reset() -> None:
await release.wait()
await original_reset()
- first._reset = blocking_reset
+ monkeypatch.setattr(first, "_reset", blocking_reset)
disconnecting = asyncio.create_task(client.realtime.disconnect())
await entered.wait()
second = client.realtime.channel("second")
diff --git a/uv.lock b/uv.lock
index 4199c535..ec0ae246 100644
--- a/uv.lock
+++ b/uv.lock
@@ -537,6 +537,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
]
+[[package]]
+name = "nodeenv"
+version = "1.10.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" },
+]
+
[[package]]
name = "openapi-python-client"
version = "0.29.0"
@@ -756,6 +765,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" },
]
+[[package]]
+name = "pyright"
+version = "1.1.411"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "nodeenv" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7e/ab/265f7dc69d28113ebba19092e57b075f41543b2ed048429c5f56e2b88eac/pyright-1.1.411.tar.gz", hash = "sha256:d885a0551f2e763b089a02702174e7f4ba77548cddabc972ab86d1f7f1b0f998", size = 4112861, upload-time = "2026-06-25T02:14:06.37Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0a/49/385be530a6a5b78d1cbcd5c2e38debc8959a2fc6bdb716f4e581002979fc/pyright-1.1.411-py3-none-any.whl", hash = "sha256:dc7c72a8e2700c55baa127554040e067041ea53ccfd50bf96308cc4291c7d5d9", size = 6181526, upload-time = "2026-06-25T02:14:04.691Z" },
+]
+
[[package]]
name = "pytest"
version = "9.1.1"
@@ -912,6 +934,7 @@ dev = [
{ name = "build" },
{ name = "mypy" },
{ name = "openapi-python-client" },
+ { name = "pyright" },
{ name = "pytest" },
{ name = "ruff" },
{ name = "types-python-dateutil" },
@@ -932,6 +955,7 @@ dev = [
{ name = "build", specifier = ">=1.5.0,<2.0.0" },
{ name = "mypy", specifier = ">=1.18.0" },
{ name = "openapi-python-client", specifier = "==0.29.0" },
+ { name = "pyright", specifier = ">=1.1.405" },
{ name = "pytest", specifier = ">=8.3.0" },
{ name = "ruff", specifier = ">=0.9.0" },
{ name = "types-python-dateutil", specifier = ">=2.9.0.20250822" },
From b11b044a2769aa8d8acb2f1042cc551acbde92e3 Mon Sep 17 00:00:00 2001
From: Sean Keever <33592180+swkeever@users.noreply.github.com>
Date: Thu, 27 Aug 2026 16:32:13 -0400
Subject: [PATCH 6/6] fix: reset realtime channels after disconnect errors
---
src/volcano_sdk/realtime.py | 10 +++++----
tests/unit/test_realtime.py | 45 +++++++++++++++++++++++++++++++++++--
2 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/src/volcano_sdk/realtime.py b/src/volcano_sdk/realtime.py
index ab6a552c..780bbbf3 100644
--- a/src/volcano_sdk/realtime.py
+++ b/src/volcano_sdk/realtime.py
@@ -375,7 +375,9 @@ async def disconnect(self) -> None:
async with self._connection_lock:
connection = self._connection
self._connection = None
- if connection is not None:
- await connection.disconnect()
- for channel in tuple(self._channels.values()):
- await channel._reset()
+ try:
+ if connection is not None:
+ await connection.disconnect()
+ finally:
+ for channel in tuple(self._channels.values()):
+ await channel._reset()
diff --git a/tests/unit/test_realtime.py b/tests/unit/test_realtime.py
index 82669728..9556ffed 100644
--- a/tests/unit/test_realtime.py
+++ b/tests/unit/test_realtime.py
@@ -5,13 +5,13 @@
from types import SimpleNamespace
from typing import TYPE_CHECKING, Any
+import pytest
+
from volcano_sdk import VolcanoClient
if TYPE_CHECKING:
from collections.abc import Awaitable, Callable
- import pytest
-
UNEXPECTED_TRANSPORT_CALL = "unexpected transport operation"
@@ -461,6 +461,47 @@ async def scenario() -> None:
assert official.calls == ["connect", "channel:broadcast:contract", "disconnect"]
+def test_realtime_disconnect_resets_channels_after_transport_failure(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ transport = AuthTransport()
+ first = FakeCentrifugeClient()
+ second = FakeCentrifugeClient()
+ clients = iter((first, second))
+
+ async def failing_disconnect() -> None:
+ first.calls.append("disconnect")
+ message = "disconnect failed"
+ raise RuntimeError(message)
+
+ monkeypatch.setattr(first, "disconnect", failing_disconnect)
+
+ def factory(*args: Any, **kwargs: Any) -> FakeCentrifugeClient:
+ del args, kwargs
+ return next(clients)
+
+ client = VolcanoClient(
+ anon_key="anon-key",
+ _transport=transport,
+ _realtime_client_factory=factory,
+ )
+ client.auth.sign_in(email="user@example.com", password="secret")
+
+ async def scenario() -> None:
+ channel = client.realtime.channel("contract")
+ await channel.subscribe()
+ with pytest.raises(RuntimeError, match="disconnect failed"):
+ await client.realtime.disconnect()
+
+ assert channel._subscription is None
+ await channel.subscribe()
+ await client.realtime.disconnect()
+
+ asyncio.run(scenario())
+ assert first.calls == ["connect", "channel:broadcast:contract", "disconnect"]
+ assert second.calls == ["connect", "channel:broadcast:contract", "disconnect"]
+
+
def test_realtime_disconnect_excludes_subscription_on_an_existing_connection(
monkeypatch: pytest.MonkeyPatch,
) -> None: