scalekit-sdk-python 2.17.0__tar.gz → 2.18.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/PKG-INFO +1 -1
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/_version.py +1 -1
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/client.py +32 -9
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/core.py +90 -9
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/PKG-INFO +1 -1
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/SOURCES.txt +2 -0
- scalekit_sdk_python-2.18.0/tests/test_http_timeout.py +59 -0
- scalekit_sdk_python-2.18.0/tests/test_keepalive_channel_options.py +87 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/LICENSE +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/README.md +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/buf/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/buf/validate/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/buf/validate/validate_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/buf/validate/validate_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/buf/validate/validate_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/pyproject.toml +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/actions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/google_adk.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/langchain.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/types/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/types/google_adk_tool.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/util.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/custom_provider.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_config.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_connection_auth_state.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_instance.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/create_connected_account_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/create_custom_provider_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/delete_custom_provider_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/list_providers_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/mcp_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/tool_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/update_connected_account_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/update_custom_provider_request.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_connected_account_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_custom_provider_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_mcp_config_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_mcp_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_mcp_session_token_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_connected_account_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_custom_provider_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_mcp_config_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_mcp_instance_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/ensure_mcp_instance_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/execute_tool_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_connected_account_auth_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_mcp_instance_auth_state_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_mcp_instance_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_mcp_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_connected_accounts_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_mcp_configs_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_mcp_connected_accounts_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_mcp_instances_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_providers_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/magic_link_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_connected_account_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_custom_provider_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_mcp_config_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_mcp_instance_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/verify_connected_account_user_response.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/tool_input_output.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/tool_mapping.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/modifier.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/types.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/auth.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/common/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/common/exceptions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/common/scalekit.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/common/user.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/connected_accounts.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/connection.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/constants/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/constants/user.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/directory.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/domain.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/events.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/frameworks/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/frameworks/django.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/frameworks/fastapi.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/frameworks/flask.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/m2m_client.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/mcp.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/middleware/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/middleware/csrf_state.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/middleware/protocol.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/middleware/session_crypto.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/middleware/session_manager.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/organization.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/passwordless.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/permissions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/providers.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/role.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/sessions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/token.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/tools.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/users.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/utils/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/utils/directory.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auditlogs/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auditlogs/auditlogs_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auditlogs/auditlogs_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auditlogs/auditlogs_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/auth_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/auth_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/auth_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/passwordless_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/passwordless_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/passwordless_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/totp_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/totp_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/totp_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/webauthn_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/webauthn_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/webauthn_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/clients/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/clients/clients_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/clients/clients_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/clients/clients_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/commons/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/commons/commons_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/commons/commons_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/commons/commons_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connected_accounts/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connections/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connections/connections_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connections/connections_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connections/connections_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/directories/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/directories/directories_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/directories/directories_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/directories/directories_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/domains/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/domains/domains_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/domains/domains_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/domains/domains_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/emails/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/emails/emails_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/emails/emails_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/emails/emails_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/environments/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/environments/environments_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/environments/environments_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/environments/environments_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/errdetails/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/errdetails/errdetails_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/errdetails/errdetails_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/errdetails/errdetails_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/events/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/events/events_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/events/events_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/events/events_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/gateway/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/gateway/gateway_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/gateway/gateway_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/gateway/gateway_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/interceptors/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/interceptors/interceptors_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/interceptors/interceptors_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/interceptors/interceptors_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/keys/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/keys/keys_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/keys/keys_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/keys/keys_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/mcp/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/mcp/mcp_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/mcp/mcp_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/mcp/mcp_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/members/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/members/members_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/members/members_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/members/members_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/migrations/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/migrations/migrations_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/migrations/migrations_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/migrations/migrations_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/options/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/options/options_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/options/options_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/options/options_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/organizations/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/organizations/organizations_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/organizations/organizations_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/organizations/organizations_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/providers/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/providers/providers_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/providers/providers_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/providers/providers_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/roles/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/roles/roles_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/roles/roles_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/roles/roles_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/secrets/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/secrets/secrets_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/secrets/secrets_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/secrets/secrets_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/sessions/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/sessions/sessions_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/sessions/sessions_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/sessions/sessions_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tokens/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tokens/tokens_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tokens/tokens_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tokens/tokens_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tools/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tools/tools_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tools/tools_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tools/tools_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/user_attributes/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/user_attributes/user_attributes_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/user_attributes/user_attributes_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/user_attributes/user_attributes_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/users/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/users/users_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/users/users_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/users/users_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/webhooks/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/webhooks/webhooks_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/webhooks/webhooks_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/webhooks/webhooks_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/workspaces/__init__.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/workspaces/workspaces_pb2.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/workspaces/workspaces_pb2.pyi +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/workspaces/workspaces_pb2_grpc.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/webauthn.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/dependency_links.txt +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/requires.txt +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/top_level.txt +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/setup.cfg +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/setup.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_actions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_connected_accounts.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_connection.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_directory.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_domain.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_events.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_login.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_m2m_client.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_mcp.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_middleware_csrf_state.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_middleware_django.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_middleware_fastapi.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_middleware_flask.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_middleware_session_crypto.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_middleware_session_manager.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_org_roles.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_organization.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_organization_session_policy.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_organization_slug_logo.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_passwordless.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_permissions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_providers.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_role_defaults_dependent.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_roles.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_sessions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_sk819_retry_behavior.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_tokens.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_tools.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_user_roles_permissions.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_users.py +0 -0
- {scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/tests/test_webauthn_credentials.py +0 -0
|
@@ -9,7 +9,7 @@ import hmac
|
|
|
9
9
|
import hashlib
|
|
10
10
|
import base64
|
|
11
11
|
from datetime import datetime, timedelta, timezone
|
|
12
|
-
from scalekit.core import CoreClient
|
|
12
|
+
from scalekit.core import CoreClient, DEFAULT_KEEPALIVE_TIME_MS, DEFAULT_KEEPALIVE_TIMEOUT_MS
|
|
13
13
|
from scalekit.domain import DomainClient
|
|
14
14
|
from scalekit.connection import ConnectionClient
|
|
15
15
|
from scalekit.m2m_client import M2MClient
|
|
@@ -50,23 +50,46 @@ webhook_signature_version = "v1"
|
|
|
50
50
|
class ScalekitClient:
|
|
51
51
|
""" Class definition for scalekit client """
|
|
52
52
|
|
|
53
|
-
def __init__(
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
env_url: str,
|
|
56
|
+
client_id: str,
|
|
57
|
+
client_secret: str,
|
|
58
|
+
keepalive_time_ms: int = DEFAULT_KEEPALIVE_TIME_MS,
|
|
59
|
+
keepalive_timeout_ms: int = DEFAULT_KEEPALIVE_TIMEOUT_MS,
|
|
60
|
+
):
|
|
54
61
|
"""
|
|
55
62
|
Initializer for Scalekit base class
|
|
56
63
|
|
|
57
|
-
:param env_url
|
|
58
|
-
:type
|
|
59
|
-
:param client_id
|
|
60
|
-
:type
|
|
61
|
-
:param client_secret
|
|
62
|
-
:type
|
|
64
|
+
:param env_url : Environment URL
|
|
65
|
+
:type : ``` str ```
|
|
66
|
+
:param client_id : Client ID
|
|
67
|
+
:type : ``` str ```
|
|
68
|
+
:param client_secret : Client Secret
|
|
69
|
+
:type : ``` str ```
|
|
70
|
+
:param keepalive_time_ms : How often, in milliseconds, an idle gRPC
|
|
71
|
+
connection is verified before reuse.
|
|
72
|
+
Defaults to 60000; most callers never
|
|
73
|
+
need to set this. Set to 0 to disable
|
|
74
|
+
keepalive entirely.
|
|
75
|
+
:type : ``` int ```
|
|
76
|
+
:param keepalive_timeout_ms : How long, in milliseconds, to wait for a
|
|
77
|
+
keepalive response before treating an
|
|
78
|
+
idle connection as dead. Defaults to
|
|
79
|
+
10000.
|
|
80
|
+
:type : ``` int ```
|
|
63
81
|
|
|
64
82
|
:returns:
|
|
65
83
|
None
|
|
66
84
|
"""
|
|
67
85
|
try:
|
|
68
86
|
self.core_client = CoreClient(
|
|
69
|
-
env_url=env_url,
|
|
87
|
+
env_url=env_url,
|
|
88
|
+
client_id=client_id,
|
|
89
|
+
client_secret=client_secret,
|
|
90
|
+
keepalive_time_ms=keepalive_time_ms,
|
|
91
|
+
keepalive_timeout_ms=keepalive_timeout_ms,
|
|
92
|
+
)
|
|
70
93
|
self.domain = DomainClient(self.core_client)
|
|
71
94
|
self.connection = ConnectionClient(self.core_client)
|
|
72
95
|
self.organization = OrganizationClient(self.core_client)
|
|
@@ -19,6 +19,33 @@ TMetadata = TypeVar("TMetadata")
|
|
|
19
19
|
TOKEN_ENDPOINT = "/oauth/token"
|
|
20
20
|
JWKS_ENDPOINT = "/keys"
|
|
21
21
|
|
|
22
|
+
# Must clear the backend's EnforcementPolicy.MinTime (30s, scalekit's
|
|
23
|
+
# cmd/grpc.go) with real margin, not just match it: grpc-core pings on this
|
|
24
|
+
# exact interval for as long as the channel is open (keepalive_permit_without_calls
|
|
25
|
+
# below), so a value equal to MinTime leaves zero room for jitter between the
|
|
26
|
+
# client's timer and the server's strike window — one early ping is a strike,
|
|
27
|
+
# three and the server GOAWAYs the connection, recreating the bug this fixes.
|
|
28
|
+
# 60s matches the Java SDK's default for the same reason.
|
|
29
|
+
DEFAULT_KEEPALIVE_TIME_MS = 60_000
|
|
30
|
+
DEFAULT_KEEPALIVE_TIMEOUT_MS = 10_000
|
|
31
|
+
|
|
32
|
+
# The floor tracks DEFAULT_KEEPALIVE_TIME_MS for the reason spelled out above:
|
|
33
|
+
# the backend's EnforcementPolicy.MinTime is 30s, and a value at exactly 30s has
|
|
34
|
+
# zero jitter headroom — grpc's ping timer drifts slightly early, so an early
|
|
35
|
+
# ping counts as a strike and enough strikes make the server GOAWAY. 60s gives
|
|
36
|
+
# 2x margin over the 30s MinTime. Since there is no legitimate reason to go below
|
|
37
|
+
# the default, the only sensible choices are 0 (disabled) or >= 60s. (gRPC also
|
|
38
|
+
# silently clamps sub-10s values up to 10s per grpc/proposal A8, so a small value
|
|
39
|
+
# never even reaches the wire as requested.) Reject 1..59999.
|
|
40
|
+
MIN_KEEPALIVE_TIME_MS = 60_000
|
|
41
|
+
|
|
42
|
+
# requests defaults to no timeout, so a black-holed connection blocks the
|
|
43
|
+
# calling thread until the OS abandons the socket. Bound the connect and read
|
|
44
|
+
# phases separately with a (connect, read) tuple.
|
|
45
|
+
DEFAULT_HTTP_CONNECT_TIMEOUT_S = 10
|
|
46
|
+
DEFAULT_HTTP_READ_TIMEOUT_S = 30
|
|
47
|
+
DEFAULT_HTTP_TIMEOUT = (DEFAULT_HTTP_CONNECT_TIMEOUT_S, DEFAULT_HTTP_READ_TIMEOUT_S)
|
|
48
|
+
|
|
22
49
|
|
|
23
50
|
class WithCall(Protocol):
|
|
24
51
|
def __call__(self, request: TRequest, metadata: TMetadata) -> TResponse: ...
|
|
@@ -32,16 +59,36 @@ class CoreClient:
|
|
|
32
59
|
api_version = "20260727"
|
|
33
60
|
user_agent = f"{sdk_version} Python/{platform.python_version()} ({platform.system()}; {platform.architecture()}"
|
|
34
61
|
|
|
35
|
-
def __init__(
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
env_url,
|
|
65
|
+
client_id,
|
|
66
|
+
client_secret,
|
|
67
|
+
keepalive_time_ms: int = DEFAULT_KEEPALIVE_TIME_MS,
|
|
68
|
+
keepalive_timeout_ms: int = DEFAULT_KEEPALIVE_TIMEOUT_MS,
|
|
69
|
+
):
|
|
36
70
|
"""
|
|
37
71
|
Initializer for Core client
|
|
38
72
|
|
|
39
|
-
:param env_url
|
|
40
|
-
:type
|
|
41
|
-
:param client_id
|
|
42
|
-
:type
|
|
43
|
-
:param client_secret
|
|
44
|
-
:type
|
|
73
|
+
:param env_url : Environment URL
|
|
74
|
+
:type : ``` str ```
|
|
75
|
+
:param client_id : Client ID
|
|
76
|
+
:type : ``` str ```
|
|
77
|
+
:param client_secret : Client Secret
|
|
78
|
+
:type : ``` str ```
|
|
79
|
+
:param keepalive_time_ms : How often, in milliseconds, an idle gRPC
|
|
80
|
+
connection is verified before reuse.
|
|
81
|
+
Must stay above the backend's keepalive
|
|
82
|
+
MinTime (30s) with real margin, or the
|
|
83
|
+
server treats this ping as abuse. Defaults
|
|
84
|
+
to 60000. Set to 0 to disable keepalive
|
|
85
|
+
entirely.
|
|
86
|
+
:type : ``` int ```
|
|
87
|
+
:param keepalive_timeout_ms : How long, in milliseconds, to wait for a
|
|
88
|
+
keepalive response before treating an
|
|
89
|
+
idle connection as dead. Defaults to
|
|
90
|
+
10000.
|
|
91
|
+
:type : ``` int ```
|
|
45
92
|
:returns
|
|
46
93
|
None
|
|
47
94
|
"""
|
|
@@ -50,6 +97,20 @@ class CoreClient:
|
|
|
50
97
|
self.env_url = env_url
|
|
51
98
|
self.client_id = client_id
|
|
52
99
|
self.client_secret = client_secret
|
|
100
|
+
# 0 means "disabled" and is allowed through deliberately; only 1..59999
|
|
101
|
+
# is rejected. A value below the 60s default leaves too little margin
|
|
102
|
+
# over the Scalekit server's 30s MinTime — an early ping gets struck as
|
|
103
|
+
# abusive and the server GOAWAYs — and gRPC silently raises sub-10s
|
|
104
|
+
# values to 10s, so a small value is never what the caller asked for.
|
|
105
|
+
if keepalive_time_ms and keepalive_time_ms < MIN_KEEPALIVE_TIME_MS:
|
|
106
|
+
raise ValueError(
|
|
107
|
+
f"keepalive_time_ms must be 0 (disabled) or >= {MIN_KEEPALIVE_TIME_MS}; "
|
|
108
|
+
f"got {keepalive_time_ms}. A value below the default leaves too little "
|
|
109
|
+
"margin over the Scalekit server's 30s MinTime (early pings are struck "
|
|
110
|
+
"as abusive), and gRPC silently raises sub-10s values to 10s."
|
|
111
|
+
)
|
|
112
|
+
self.keepalive_time_ms = keepalive_time_ms
|
|
113
|
+
self.keepalive_timeout_ms = keepalive_timeout_ms
|
|
53
114
|
self.keys = {}
|
|
54
115
|
self.access_token = None
|
|
55
116
|
self.grpc_secure_channel = None
|
|
@@ -70,7 +131,24 @@ class CoreClient:
|
|
|
70
131
|
channel_credentials,
|
|
71
132
|
call_credentials,
|
|
72
133
|
)
|
|
73
|
-
|
|
134
|
+
# keepalive_time_ms == 0 disables keepalive entirely: no options are
|
|
135
|
+
# passed, so grpc-core falls back to its own defaults (no idle pings).
|
|
136
|
+
channel_options = []
|
|
137
|
+
if self.keepalive_time_ms:
|
|
138
|
+
# keepalive_permit_without_calls=1 so an idle channel is still
|
|
139
|
+
# periodically verified: without it, grpc-core only sends HTTP/2
|
|
140
|
+
# keepalive PINGs while there are active calls, so a connection
|
|
141
|
+
# silently dropped by a network intermediary while idle isn't
|
|
142
|
+
# detected until the next real call is written to it.
|
|
143
|
+
channel_options = [
|
|
144
|
+
('grpc.keepalive_time_ms', self.keepalive_time_ms),
|
|
145
|
+
('grpc.keepalive_timeout_ms', self.keepalive_timeout_ms),
|
|
146
|
+
('grpc.keepalive_permit_without_calls', 1),
|
|
147
|
+
('grpc.http2.max_pings_without_data', 0),
|
|
148
|
+
]
|
|
149
|
+
self.grpc_secure_channel = grpc.secure_channel(
|
|
150
|
+
self.host, composite_credentials, options=channel_options
|
|
151
|
+
)
|
|
74
152
|
|
|
75
153
|
def __authenticate_client(self):
|
|
76
154
|
"""
|
|
@@ -104,6 +182,7 @@ class CoreClient:
|
|
|
104
182
|
headers=self.get_headers(headers=headers),
|
|
105
183
|
data=data,
|
|
106
184
|
verify=True,
|
|
185
|
+
timeout=DEFAULT_HTTP_TIMEOUT,
|
|
107
186
|
)
|
|
108
187
|
if response.status_code != 200:
|
|
109
188
|
raise ScalekitServerException.promote(response)
|
|
@@ -114,7 +193,9 @@ class CoreClient:
|
|
|
114
193
|
if self.keys and len(self.keys) > 0:
|
|
115
194
|
return
|
|
116
195
|
response = requests.get(
|
|
117
|
-
self.env_url + JWKS_ENDPOINT,
|
|
196
|
+
self.env_url + JWKS_ENDPOINT,
|
|
197
|
+
headers=self.get_headers(),
|
|
198
|
+
timeout=DEFAULT_HTTP_TIMEOUT,
|
|
118
199
|
)
|
|
119
200
|
response = json.loads(response.content)
|
|
120
201
|
keys = response["keys"]
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/SOURCES.txt
RENAMED
|
@@ -247,6 +247,8 @@ tests/test_connection.py
|
|
|
247
247
|
tests/test_directory.py
|
|
248
248
|
tests/test_domain.py
|
|
249
249
|
tests/test_events.py
|
|
250
|
+
tests/test_http_timeout.py
|
|
251
|
+
tests/test_keepalive_channel_options.py
|
|
250
252
|
tests/test_login.py
|
|
251
253
|
tests/test_m2m_client.py
|
|
252
254
|
tests/test_mcp.py
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests that the HTTP calls in CoreClient pass a bounded timeout.
|
|
3
|
+
|
|
4
|
+
requests has no default timeout, so a black-holed connection would block the
|
|
5
|
+
calling thread indefinitely. authenticate() and get_jwks() must pass a
|
|
6
|
+
non-None timeout to requests.post / requests.get.
|
|
7
|
+
"""
|
|
8
|
+
import json
|
|
9
|
+
import unittest
|
|
10
|
+
from unittest.mock import MagicMock, patch
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _make_core_client():
|
|
14
|
+
"""Return a CoreClient instance with __init__ bypassed (no real network calls)."""
|
|
15
|
+
from scalekit.core import CoreClient
|
|
16
|
+
client = CoreClient.__new__(CoreClient)
|
|
17
|
+
client.access_token = "test-token"
|
|
18
|
+
client.host = "example.com"
|
|
19
|
+
client.env_url = "https://example.com"
|
|
20
|
+
client.client_id = "cid"
|
|
21
|
+
client.client_secret = "csec"
|
|
22
|
+
client.keys = {}
|
|
23
|
+
client.grpc_secure_channel = None
|
|
24
|
+
return client
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestHttpTimeout(unittest.TestCase):
|
|
28
|
+
def setUp(self):
|
|
29
|
+
self.client = _make_core_client()
|
|
30
|
+
|
|
31
|
+
def test_authenticate_passes_timeout_to_requests_post(self):
|
|
32
|
+
"""authenticate() must pass a non-None timeout to requests.post."""
|
|
33
|
+
mock_response = MagicMock()
|
|
34
|
+
mock_response.status_code = 200
|
|
35
|
+
|
|
36
|
+
with patch("scalekit.core.requests.post", return_value=mock_response) as mock_post:
|
|
37
|
+
self.client.authenticate(data={"grant_type": "client_credentials"})
|
|
38
|
+
|
|
39
|
+
mock_post.assert_called_once()
|
|
40
|
+
_, kwargs = mock_post.call_args
|
|
41
|
+
self.assertIn("timeout", kwargs)
|
|
42
|
+
self.assertIsNotNone(kwargs["timeout"])
|
|
43
|
+
|
|
44
|
+
def test_get_jwks_passes_timeout_to_requests_get(self):
|
|
45
|
+
"""get_jwks() must pass a non-None timeout to requests.get."""
|
|
46
|
+
mock_response = MagicMock()
|
|
47
|
+
mock_response.content = json.dumps({"keys": []}).encode("utf-8")
|
|
48
|
+
|
|
49
|
+
with patch("scalekit.core.requests.get", return_value=mock_response) as mock_get:
|
|
50
|
+
self.client.get_jwks()
|
|
51
|
+
|
|
52
|
+
mock_get.assert_called_once()
|
|
53
|
+
_, kwargs = mock_get.call_args
|
|
54
|
+
self.assertIn("timeout", kwargs)
|
|
55
|
+
self.assertIsNotNone(kwargs["timeout"])
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == "__main__":
|
|
59
|
+
unittest.main()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for gRPC keepalive channel options in CoreClient.
|
|
3
|
+
|
|
4
|
+
Covers the runtime escape hatch (keepalive_time_ms=0 disables keepalive) and
|
|
5
|
+
the sub-10s validation guard (gRPC clamps values below 10s up to 10s, which
|
|
6
|
+
the Scalekit server rejects).
|
|
7
|
+
|
|
8
|
+
These tests never touch the network: __authenticate_client is mocked and
|
|
9
|
+
grpc.secure_channel is mocked, so only the channel-option wiring is exercised.
|
|
10
|
+
"""
|
|
11
|
+
import unittest
|
|
12
|
+
from unittest.mock import patch
|
|
13
|
+
|
|
14
|
+
from scalekit.core import (
|
|
15
|
+
CoreClient,
|
|
16
|
+
DEFAULT_KEEPALIVE_TIME_MS,
|
|
17
|
+
DEFAULT_KEEPALIVE_TIMEOUT_MS,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _build_client(**kwargs):
|
|
22
|
+
"""Construct a CoreClient with auth and channel creation stubbed.
|
|
23
|
+
|
|
24
|
+
Returns (client, mock_secure_channel) so tests can assert on the options
|
|
25
|
+
passed to grpc.secure_channel.
|
|
26
|
+
"""
|
|
27
|
+
with patch.object(CoreClient, "_CoreClient__authenticate_client"), \
|
|
28
|
+
patch("scalekit.core.grpc.secure_channel") as mock_secure_channel, \
|
|
29
|
+
patch("scalekit.core.grpc.ssl_channel_credentials"), \
|
|
30
|
+
patch("scalekit.core.grpc.access_token_call_credentials"), \
|
|
31
|
+
patch("scalekit.core.grpc.composite_channel_credentials"):
|
|
32
|
+
client = CoreClient(
|
|
33
|
+
env_url="https://example.com",
|
|
34
|
+
client_id="cid",
|
|
35
|
+
client_secret="csec",
|
|
36
|
+
**kwargs,
|
|
37
|
+
)
|
|
38
|
+
return client, mock_secure_channel
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class TestKeepaliveChannelOptions(unittest.TestCase):
|
|
42
|
+
def _options_from(self, mock_secure_channel):
|
|
43
|
+
"""Extract the options kwarg from the secure_channel call."""
|
|
44
|
+
mock_secure_channel.assert_called_once()
|
|
45
|
+
_, kwargs = mock_secure_channel.call_args
|
|
46
|
+
return kwargs["options"]
|
|
47
|
+
|
|
48
|
+
def test_disabled_passes_empty_options(self):
|
|
49
|
+
"""keepalive_time_ms=0 must call secure_channel with options=[]."""
|
|
50
|
+
_, mock_secure_channel = _build_client(keepalive_time_ms=0)
|
|
51
|
+
self.assertEqual(self._options_from(mock_secure_channel), [])
|
|
52
|
+
|
|
53
|
+
def test_default_construction_includes_all_four_options(self):
|
|
54
|
+
"""Default construction must include all four expected option tuples."""
|
|
55
|
+
_, mock_secure_channel = _build_client()
|
|
56
|
+
options = self._options_from(mock_secure_channel)
|
|
57
|
+
self.assertEqual(
|
|
58
|
+
options,
|
|
59
|
+
[
|
|
60
|
+
('grpc.keepalive_time_ms', DEFAULT_KEEPALIVE_TIME_MS),
|
|
61
|
+
('grpc.keepalive_timeout_ms', DEFAULT_KEEPALIVE_TIMEOUT_MS),
|
|
62
|
+
('grpc.keepalive_permit_without_calls', 1),
|
|
63
|
+
('grpc.http2.max_pings_without_data', 0),
|
|
64
|
+
],
|
|
65
|
+
)
|
|
66
|
+
# Explicit check on the documented default value.
|
|
67
|
+
self.assertIn(('grpc.keepalive_time_ms', 60000), options)
|
|
68
|
+
|
|
69
|
+
def test_below_minimum_raises_value_error(self):
|
|
70
|
+
"""keepalive_time_ms below the 60s minimum must raise ValueError."""
|
|
71
|
+
with self.assertRaises(ValueError):
|
|
72
|
+
_build_client(keepalive_time_ms=5000)
|
|
73
|
+
|
|
74
|
+
def test_thirty_seconds_now_raises_value_error(self):
|
|
75
|
+
"""keepalive_time_ms=30000 is below the 60s minimum and must raise ValueError."""
|
|
76
|
+
with self.assertRaises(ValueError):
|
|
77
|
+
_build_client(keepalive_time_ms=30000)
|
|
78
|
+
|
|
79
|
+
def test_sixty_seconds_boundary_accepted(self):
|
|
80
|
+
"""keepalive_time_ms=60000 is the boundary and must be accepted."""
|
|
81
|
+
_, mock_secure_channel = _build_client(keepalive_time_ms=60000)
|
|
82
|
+
options = self._options_from(mock_secure_channel)
|
|
83
|
+
self.assertIn(('grpc.keepalive_time_ms', 60000), options)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
87
|
+
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/__init__.py
RENAMED
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/google_adk.py
RENAMED
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/langchain.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/util.py
RENAMED
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/__init__.py
RENAMED
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/custom_provider.py
RENAMED
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_instance.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/tool_mapping.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/middleware/session_crypto.py
RENAMED
|
File without changes
|
{scalekit_sdk_python-2.17.0 → scalekit_sdk_python-2.18.0}/scalekit/middleware/session_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|