scalekit-sdk-python 2.8.0__tar.gz → 2.10.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.
Files changed (258) hide show
  1. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/PKG-INFO +1 -1
  2. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/_version.py +1 -1
  3. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/actions.py +196 -10
  4. scalekit_sdk_python-2.10.0/scalekit/actions/models/custom_provider.py +348 -0
  5. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/requests/create_connected_account_request.py +13 -2
  6. scalekit_sdk_python-2.10.0/scalekit/actions/models/requests/create_custom_provider_request.py +74 -0
  7. scalekit_sdk_python-2.10.0/scalekit/actions/models/requests/delete_custom_provider_request.py +22 -0
  8. scalekit_sdk_python-2.10.0/scalekit/actions/models/requests/list_providers_request.py +56 -0
  9. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/requests/update_connected_account_request.py +12 -1
  10. scalekit_sdk_python-2.10.0/scalekit/actions/models/requests/update_custom_provider_request.py +71 -0
  11. scalekit_sdk_python-2.10.0/scalekit/actions/models/responses/create_custom_provider_response.py +46 -0
  12. scalekit_sdk_python-2.10.0/scalekit/actions/models/responses/delete_custom_provider_response.py +32 -0
  13. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/get_connected_account_auth_response.py +48 -4
  14. scalekit_sdk_python-2.10.0/scalekit/actions/models/responses/list_providers_response.py +65 -0
  15. scalekit_sdk_python-2.10.0/scalekit/actions/models/responses/update_custom_provider_response.py +45 -0
  16. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/types.py +23 -1
  17. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/client.py +4 -2
  18. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/connected_accounts.py +36 -0
  19. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/connection.py +70 -0
  20. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/core.py +1 -1
  21. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/organization.py +75 -0
  22. scalekit_sdk_python-2.10.0/scalekit/providers.py +211 -0
  23. scalekit_sdk_python-2.10.0/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.py +62 -0
  24. scalekit_sdk_python-2.10.0/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.pyi +91 -0
  25. scalekit_sdk_python-2.10.0/scalekit/v1/agentkit_logs/agentkit_analytics_pb2_grpc.py +66 -0
  26. scalekit_sdk_python-2.10.0/scalekit/v1/agentkit_logs/agentkit_logs_pb2.py +80 -0
  27. scalekit_sdk_python-2.10.0/scalekit/v1/agentkit_logs/agentkit_logs_pb2.pyi +101 -0
  28. scalekit_sdk_python-2.10.0/scalekit/v1/agentkit_logs/agentkit_logs_pb2_grpc.py +99 -0
  29. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/auth_pb2.py +42 -38
  30. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/auth_pb2.pyi +8 -4
  31. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/clients/clients_pb2.py +36 -28
  32. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/clients/clients_pb2.pyi +12 -2
  33. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/commons/commons_pb2.py +3 -1
  34. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/commons/commons_pb2.pyi +11 -0
  35. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.py +45 -13
  36. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi +44 -2
  37. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py +102 -0
  38. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/connections/connections_pb2.py +157 -137
  39. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/connections/connections_pb2.pyi +32 -6
  40. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/domains/domains_pb2.py +48 -39
  41. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/domains/domains_pb2.pyi +22 -2
  42. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/domains/domains_pb2_grpc.py +3 -4
  43. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/environments/environments_pb2.py +52 -50
  44. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/environments/environments_pb2.pyi +8 -4
  45. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/options/options_pb2.py +2 -2
  46. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/options/options_pb2.pyi +14 -0
  47. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/organizations/organizations_pb2.py +98 -84
  48. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/organizations/organizations_pb2.pyi +91 -66
  49. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/organizations/organizations_pb2_grpc.py +53 -86
  50. scalekit_sdk_python-2.10.0/scalekit/v1/providers/providers_pb2.py +184 -0
  51. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/providers/providers_pb2.pyi +37 -6
  52. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/tools/tools_pb2.py +28 -26
  53. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/tools/tools_pb2.pyi +4 -2
  54. scalekit_sdk_python-2.10.0/scalekit/v1/workspaces/__init__.py +0 -0
  55. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit_sdk_python.egg-info/PKG-INFO +1 -1
  56. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit_sdk_python.egg-info/SOURCES.txt +19 -0
  57. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_actions.py +136 -2
  58. scalekit_sdk_python-2.10.0/tests/test_connection.py +238 -0
  59. scalekit_sdk_python-2.10.0/tests/test_organization_session_policy.py +107 -0
  60. scalekit_sdk_python-2.10.0/tests/test_providers.py +260 -0
  61. scalekit_sdk_python-2.8.0/scalekit/v1/providers/providers_pb2.py +0 -162
  62. scalekit_sdk_python-2.8.0/tests/test_connection.py +0 -100
  63. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/LICENSE +0 -0
  64. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/README.md +0 -0
  65. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/__init__.py +0 -0
  66. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/__init__.py +0 -0
  67. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/expression_pb2.py +0 -0
  68. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/expression_pb2.pyi +0 -0
  69. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/expression_pb2_grpc.py +0 -0
  70. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/priv/__init__.py +0 -0
  71. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/priv/private_pb2.py +0 -0
  72. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/priv/private_pb2.pyi +0 -0
  73. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/priv/private_pb2_grpc.py +0 -0
  74. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/validate_pb2.py +0 -0
  75. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/validate_pb2.pyi +0 -0
  76. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/buf/validate/validate_pb2_grpc.py +0 -0
  77. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/pyproject.toml +0 -0
  78. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/__init__.py +0 -0
  79. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/__init__.py +0 -0
  80. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/frameworks/__init__.py +0 -0
  81. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/frameworks/google_adk.py +0 -0
  82. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/frameworks/langchain.py +0 -0
  83. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/frameworks/types/__init__.py +0 -0
  84. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/frameworks/types/google_adk_tool.py +0 -0
  85. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/frameworks/util.py +0 -0
  86. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/__init__.py +0 -0
  87. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/mcp_config.py +0 -0
  88. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/mcp_instance.py +0 -0
  89. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/requests/__init__.py +0 -0
  90. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/requests/mcp_request.py +0 -0
  91. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/requests/tool_request.py +0 -0
  92. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/__init__.py +0 -0
  93. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/create_connected_account_response.py +0 -0
  94. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/create_mcp_config_response.py +0 -0
  95. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/create_mcp_response.py +0 -0
  96. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/delete_connected_account_response.py +0 -0
  97. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/delete_mcp_config_response.py +0 -0
  98. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/delete_mcp_instance_response.py +0 -0
  99. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/ensure_mcp_instance_response.py +0 -0
  100. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/execute_tool_response.py +0 -0
  101. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/get_mcp_instance_auth_state_response.py +0 -0
  102. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/get_mcp_instance_response.py +0 -0
  103. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/get_mcp_response.py +0 -0
  104. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/list_connected_accounts_response.py +0 -0
  105. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/list_mcp_configs_response.py +0 -0
  106. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/list_mcp_instances_response.py +0 -0
  107. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/magic_link_response.py +0 -0
  108. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/update_connected_account_response.py +0 -0
  109. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/update_mcp_config_response.py +0 -0
  110. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/update_mcp_instance_response.py +0 -0
  111. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/responses/verify_connected_account_user_response.py +0 -0
  112. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/tool_input_output.py +0 -0
  113. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/models/tool_mapping.py +0 -0
  114. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/actions/modifier.py +0 -0
  115. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/auth.py +0 -0
  116. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/common/__init__.py +0 -0
  117. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/common/exceptions.py +0 -0
  118. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/common/scalekit.py +0 -0
  119. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/common/user.py +0 -0
  120. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/constants/__init__.py +0 -0
  121. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/constants/user.py +0 -0
  122. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/directory.py +0 -0
  123. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/domain.py +0 -0
  124. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/m2m_client.py +0 -0
  125. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/mcp.py +0 -0
  126. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/passwordless.py +0 -0
  127. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/permissions.py +0 -0
  128. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/role.py +0 -0
  129. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/sessions.py +0 -0
  130. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/token.py +0 -0
  131. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/tools.py +0 -0
  132. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/users.py +0 -0
  133. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/utils/__init__.py +0 -0
  134. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/utils/directory.py +0 -0
  135. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/__init__.py +0 -0
  136. {scalekit_sdk_python-2.8.0/scalekit/v1/auditlogs → scalekit_sdk_python-2.10.0/scalekit/v1/agentkit_logs}/__init__.py +0 -0
  137. {scalekit_sdk_python-2.8.0/scalekit/v1/auth → scalekit_sdk_python-2.10.0/scalekit/v1/auditlogs}/__init__.py +0 -0
  138. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auditlogs/auditlogs_pb2.py +0 -0
  139. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auditlogs/auditlogs_pb2.pyi +0 -0
  140. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auditlogs/auditlogs_pb2_grpc.py +0 -0
  141. {scalekit_sdk_python-2.8.0/scalekit/v1/clients → scalekit_sdk_python-2.10.0/scalekit/v1/auth}/__init__.py +0 -0
  142. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/auth_pb2_grpc.py +0 -0
  143. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/passwordless_pb2.py +0 -0
  144. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/passwordless_pb2.pyi +0 -0
  145. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/passwordless_pb2_grpc.py +0 -0
  146. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/totp_pb2.py +0 -0
  147. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/totp_pb2.pyi +0 -0
  148. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/totp_pb2_grpc.py +0 -0
  149. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/webauthn_pb2.py +0 -0
  150. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/webauthn_pb2.pyi +0 -0
  151. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/auth/webauthn_pb2_grpc.py +0 -0
  152. {scalekit_sdk_python-2.8.0/scalekit/v1/commons → scalekit_sdk_python-2.10.0/scalekit/v1/clients}/__init__.py +0 -0
  153. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/clients/clients_pb2_grpc.py +0 -0
  154. {scalekit_sdk_python-2.8.0/scalekit/v1/connected_accounts → scalekit_sdk_python-2.10.0/scalekit/v1/commons}/__init__.py +0 -0
  155. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/commons/commons_pb2_grpc.py +0 -0
  156. {scalekit_sdk_python-2.8.0/scalekit/v1/connections → scalekit_sdk_python-2.10.0/scalekit/v1/connected_accounts}/__init__.py +0 -0
  157. {scalekit_sdk_python-2.8.0/scalekit/v1/directories → scalekit_sdk_python-2.10.0/scalekit/v1/connections}/__init__.py +0 -0
  158. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/connections/connections_pb2_grpc.py +0 -0
  159. {scalekit_sdk_python-2.8.0/scalekit/v1/domains → scalekit_sdk_python-2.10.0/scalekit/v1/directories}/__init__.py +0 -0
  160. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/directories/directories_pb2.py +0 -0
  161. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/directories/directories_pb2.pyi +0 -0
  162. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/directories/directories_pb2_grpc.py +0 -0
  163. {scalekit_sdk_python-2.8.0/scalekit/v1/emails → scalekit_sdk_python-2.10.0/scalekit/v1/domains}/__init__.py +0 -0
  164. {scalekit_sdk_python-2.8.0/scalekit/v1/environments → scalekit_sdk_python-2.10.0/scalekit/v1/emails}/__init__.py +0 -0
  165. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/emails/emails_pb2.py +0 -0
  166. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/emails/emails_pb2.pyi +0 -0
  167. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/emails/emails_pb2_grpc.py +0 -0
  168. {scalekit_sdk_python-2.8.0/scalekit/v1/errdetails → scalekit_sdk_python-2.10.0/scalekit/v1/environments}/__init__.py +0 -0
  169. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/environments/environments_pb2_grpc.py +0 -0
  170. {scalekit_sdk_python-2.8.0/scalekit/v1/events → scalekit_sdk_python-2.10.0/scalekit/v1/errdetails}/__init__.py +0 -0
  171. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/errdetails/errdetails_pb2.py +0 -0
  172. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/errdetails/errdetails_pb2.pyi +0 -0
  173. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/errdetails/errdetails_pb2_grpc.py +0 -0
  174. {scalekit_sdk_python-2.8.0/scalekit/v1/interceptors → scalekit_sdk_python-2.10.0/scalekit/v1/events}/__init__.py +0 -0
  175. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/events/events_pb2.py +0 -0
  176. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/events/events_pb2.pyi +0 -0
  177. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/events/events_pb2_grpc.py +0 -0
  178. {scalekit_sdk_python-2.8.0/scalekit/v1/keys → scalekit_sdk_python-2.10.0/scalekit/v1/interceptors}/__init__.py +0 -0
  179. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/interceptors/interceptors_pb2.py +0 -0
  180. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/interceptors/interceptors_pb2.pyi +0 -0
  181. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/interceptors/interceptors_pb2_grpc.py +0 -0
  182. {scalekit_sdk_python-2.8.0/scalekit/v1/mcp → scalekit_sdk_python-2.10.0/scalekit/v1/keys}/__init__.py +0 -0
  183. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/keys/keys_pb2.py +0 -0
  184. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/keys/keys_pb2.pyi +0 -0
  185. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/keys/keys_pb2_grpc.py +0 -0
  186. {scalekit_sdk_python-2.8.0/scalekit/v1/members → scalekit_sdk_python-2.10.0/scalekit/v1/mcp}/__init__.py +0 -0
  187. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/mcp/mcp_pb2.py +0 -0
  188. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/mcp/mcp_pb2.pyi +0 -0
  189. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/mcp/mcp_pb2_grpc.py +0 -0
  190. {scalekit_sdk_python-2.8.0/scalekit/v1/migrations → scalekit_sdk_python-2.10.0/scalekit/v1/members}/__init__.py +0 -0
  191. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/members/members_pb2.py +0 -0
  192. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/members/members_pb2.pyi +0 -0
  193. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/members/members_pb2_grpc.py +0 -0
  194. {scalekit_sdk_python-2.8.0/scalekit/v1/options → scalekit_sdk_python-2.10.0/scalekit/v1/migrations}/__init__.py +0 -0
  195. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/migrations/migrations_pb2.py +0 -0
  196. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/migrations/migrations_pb2.pyi +0 -0
  197. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/migrations/migrations_pb2_grpc.py +0 -0
  198. {scalekit_sdk_python-2.8.0/scalekit/v1/organizations → scalekit_sdk_python-2.10.0/scalekit/v1/options}/__init__.py +0 -0
  199. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/options/options_pb2_grpc.py +0 -0
  200. {scalekit_sdk_python-2.8.0/scalekit/v1/providers → scalekit_sdk_python-2.10.0/scalekit/v1/organizations}/__init__.py +0 -0
  201. {scalekit_sdk_python-2.8.0/scalekit/v1/roles → scalekit_sdk_python-2.10.0/scalekit/v1/providers}/__init__.py +0 -0
  202. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/providers/providers_pb2_grpc.py +0 -0
  203. {scalekit_sdk_python-2.8.0/scalekit/v1/secrets → scalekit_sdk_python-2.10.0/scalekit/v1/roles}/__init__.py +0 -0
  204. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/roles/roles_pb2.py +0 -0
  205. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/roles/roles_pb2.pyi +0 -0
  206. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/roles/roles_pb2_grpc.py +0 -0
  207. {scalekit_sdk_python-2.8.0/scalekit/v1/sessions → scalekit_sdk_python-2.10.0/scalekit/v1/secrets}/__init__.py +0 -0
  208. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/secrets/secrets_pb2.py +0 -0
  209. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/secrets/secrets_pb2.pyi +0 -0
  210. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/secrets/secrets_pb2_grpc.py +0 -0
  211. {scalekit_sdk_python-2.8.0/scalekit/v1/tokens → scalekit_sdk_python-2.10.0/scalekit/v1/sessions}/__init__.py +0 -0
  212. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/sessions/sessions_pb2.py +0 -0
  213. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/sessions/sessions_pb2.pyi +0 -0
  214. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/sessions/sessions_pb2_grpc.py +0 -0
  215. {scalekit_sdk_python-2.8.0/scalekit/v1/tools → scalekit_sdk_python-2.10.0/scalekit/v1/tokens}/__init__.py +0 -0
  216. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/tokens/tokens_pb2.py +0 -0
  217. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/tokens/tokens_pb2.pyi +0 -0
  218. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/tokens/tokens_pb2_grpc.py +0 -0
  219. {scalekit_sdk_python-2.8.0/scalekit/v1/user_attributes → scalekit_sdk_python-2.10.0/scalekit/v1/tools}/__init__.py +0 -0
  220. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/tools/tools_pb2_grpc.py +0 -0
  221. {scalekit_sdk_python-2.8.0/scalekit/v1/users → scalekit_sdk_python-2.10.0/scalekit/v1/user_attributes}/__init__.py +0 -0
  222. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/user_attributes/user_attributes_pb2.py +0 -0
  223. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/user_attributes/user_attributes_pb2.pyi +0 -0
  224. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/user_attributes/user_attributes_pb2_grpc.py +0 -0
  225. {scalekit_sdk_python-2.8.0/scalekit/v1/webhooks → scalekit_sdk_python-2.10.0/scalekit/v1/users}/__init__.py +0 -0
  226. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/users/users_pb2.py +0 -0
  227. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/users/users_pb2.pyi +0 -0
  228. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/users/users_pb2_grpc.py +0 -0
  229. {scalekit_sdk_python-2.8.0/scalekit/v1/workspaces → scalekit_sdk_python-2.10.0/scalekit/v1/webhooks}/__init__.py +0 -0
  230. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/webhooks/webhooks_pb2.py +0 -0
  231. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/webhooks/webhooks_pb2.pyi +0 -0
  232. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/webhooks/webhooks_pb2_grpc.py +0 -0
  233. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/workspaces/workspaces_pb2.py +0 -0
  234. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/workspaces/workspaces_pb2.pyi +0 -0
  235. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/v1/workspaces/workspaces_pb2_grpc.py +0 -0
  236. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit/webauthn.py +0 -0
  237. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit_sdk_python.egg-info/dependency_links.txt +0 -0
  238. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit_sdk_python.egg-info/requires.txt +0 -0
  239. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/scalekit_sdk_python.egg-info/top_level.txt +0 -0
  240. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/setup.cfg +0 -0
  241. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/setup.py +0 -0
  242. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_connected_accounts.py +0 -0
  243. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_directory.py +0 -0
  244. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_domain.py +0 -0
  245. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_m2m_client.py +0 -0
  246. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_mcp.py +0 -0
  247. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_org_roles.py +0 -0
  248. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_organization.py +0 -0
  249. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_passwordless.py +0 -0
  250. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_permissions.py +0 -0
  251. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_role_defaults_dependent.py +0 -0
  252. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_roles.py +0 -0
  253. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_sessions.py +0 -0
  254. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_tokens.py +0 -0
  255. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_tools.py +0 -0
  256. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_user_roles_permissions.py +0 -0
  257. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_users.py +0 -0
  258. {scalekit_sdk_python-2.8.0 → scalekit_sdk_python-2.10.0}/tests/test_webauthn_credentials.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scalekit-sdk-python
3
- Version: 2.8.0
3
+ Version: 2.10.0
4
4
  Summary: Scalekit official Python SDK
5
5
  Home-page: https://github.com/scalekit-inc/scalekit-sdk-python
6
6
  Author: Team Scalekit
@@ -1,3 +1,3 @@
1
1
  # Single source of truth for the SDK version.
2
2
  # Import this in setup.py and scalekit/core.py — never hardcode the version elsewhere.
3
- __version__ = "2.8.0"
3
+ __version__ = "2.10.0"
@@ -1,9 +1,11 @@
1
1
  from typing import Optional, Any, List, Dict, Union
2
2
  import requests
3
- from scalekit.actions.types import ToolRequest,ExecuteToolResponse,MagicLinkResponse,ListConnectedAccountsResponse,DeleteConnectedAccountResponse,GetConnectedAccountAuthResponse,ToolInput, \
3
+ from scalekit.actions.types import ToolRequest,ExecuteToolResponse,MagicLinkResponse,ListConnectedAccountsResponse,DeleteConnectedAccountResponse,GetConnectedAccountAuthResponse,GetConnectedAccountDetailsResponse,ToolInput, \
4
4
  UpdateConnectedAccountResponse,CreateMcpConfigResponse,ListMcpConfigsResponse,UpdateMcpConfigResponse,DeleteMcpConfigResponse, \
5
5
  EnsureMcpInstanceResponse,UpdateMcpInstanceResponse,GetMcpInstanceResponse,ListMcpInstancesResponse,DeleteMcpInstanceResponse,GetMcpInstanceAuthStateResponse, \
6
- McpConfig,McpConfigConnectionToolMapping,VerifyConnectedAccountUserResponse
6
+ McpConfig,McpConfigConnectionToolMapping,VerifyConnectedAccountUserResponse, \
7
+ CreateCustomProviderRequest,UpdateCustomProviderRequest,ListProvidersRequest,DeleteCustomProviderRequest, \
8
+ CreateCustomProviderResponse,UpdateCustomProviderResponse,ListProvidersResponse,DeleteCustomProviderResponse
7
9
  from scalekit.actions.models.responses.create_connected_account_response import CreateConnectedAccountResponse
8
10
  from scalekit.actions.models.requests.create_connected_account_request import CreateConnectedAccountRequest
9
11
  from scalekit.actions.models.requests.update_connected_account_request import UpdateConnectedAccountRequest
@@ -19,17 +21,19 @@ from scalekit.common.exceptions import ScalekitNotFoundException
19
21
  class ActionClient:
20
22
  """Class definition for Connect Client"""
21
23
 
22
- def __init__(self,tools_client, connected_accounts_client, mcp_client=None):
24
+ def __init__(self,tools_client, connected_accounts_client, mcp_client=None, providers_client=None):
23
25
  """
24
26
  Initialize ActionClient with tools, connected accounts, and MCP dependencies
25
-
27
+
26
28
  :param tools_client: ToolsClient instance
27
29
  :type: ToolsClient
28
30
  :param connected_accounts_client: ConnectedAccountsClient instance
29
31
  :type: ConnectedAccountsClient
30
32
  :param mcp_client: McpClient instance (optional)
31
33
  :type: McpClient
32
-
34
+ :param providers_client: ProvidersClient instance (optional)
35
+ :type: ProvidersClient
36
+
33
37
  :returns:
34
38
  None
35
39
  """
@@ -38,6 +42,8 @@ class ActionClient:
38
42
  self.connected_accounts = connected_accounts_client
39
43
  self._mcp_client = mcp_client
40
44
  self._mcp_actions = None
45
+ self._providers_client = providers_client
46
+ self._providers_actions = None
41
47
  self._modifiers: List[Modifier] = []
42
48
  self._google = None
43
49
  self._langchain = None
@@ -87,6 +93,20 @@ class ActionClient:
87
93
  self._mcp_actions = ActionMcp(self)
88
94
  return self._mcp_actions
89
95
 
96
+ @property
97
+ def providers(self) -> "ActionProviders":
98
+ """Expose custom provider CRUD with typed request and response objects.
99
+
100
+ :returns: ActionProviders instance bound to the configured ProvidersClient.
101
+ :rtype: ActionProviders
102
+ :raises ValueError: If no ProvidersClient was passed at construction time.
103
+ """
104
+ if self._providers_client is None:
105
+ raise ValueError("Providers client not initialized.")
106
+ if self._providers_actions is None:
107
+ self._providers_actions = ActionProviders(self._providers_client)
108
+ return self._providers_actions
109
+
90
110
  def execute_tool(
91
111
  self,
92
112
  tool_input:ToolInput,
@@ -323,7 +343,51 @@ class ActionClient:
323
343
 
324
344
  # Convert proto to our GetConnectedAccountAuthResponse class
325
345
  return GetConnectedAccountAuthResponse.from_proto(proto_response)
326
-
346
+
347
+ def get_connected_account_details(
348
+ self,
349
+ connection_name: Optional[str] = None,
350
+ identifier: Optional[str] = None,
351
+ connected_account_id: Optional[str] = None,
352
+ **kwargs
353
+ ) -> GetConnectedAccountDetailsResponse:
354
+ """
355
+ Get connected account details by identifier, without auth credentials.
356
+
357
+ Use this instead of :meth:`get_connected_account` when you only need
358
+ account metadata (status, connector, api_config, etc.) and do not
359
+ require the access/refresh tokens.
360
+
361
+ You must provide **one** of the following to identify the connected account:
362
+
363
+ - ``connection_name`` **and** ``identifier`` — use when you know the
364
+ connector name and the end-user's identifier (e.g. email address).
365
+ - ``connected_account_id`` — use when you already hold the Scalekit
366
+ connected account ID.
367
+
368
+ :param connection_name: Connector identifier, e.g. ``"salesforce-1hpnGzcD"``.
369
+ Required when ``connected_account_id`` is not provided.
370
+ :type connection_name: str
371
+ :param identifier: End-user identifier tied to the connected account,
372
+ e.g. ``"john.doe"``. Required when ``connected_account_id`` is not provided.
373
+ :type identifier: str
374
+ :param connected_account_id: Scalekit connected account ID. When supplied,
375
+ ``connection_name`` and ``identifier`` are ignored.
376
+ :type connected_account_id: str
377
+
378
+ :returns:
379
+ GetConnectedAccountDetailsResponse containing account metadata
380
+ without auth credentials
381
+ :rtype: GetConnectedAccountDetailsResponse
382
+ """
383
+ result_tuple = self.connected_accounts.get_connected_account_details_by_identifier(
384
+ connector=connection_name,
385
+ identifier=identifier,
386
+ connected_account_id=connected_account_id
387
+ )
388
+ proto_response = result_tuple[0]
389
+ return GetConnectedAccountDetailsResponse.from_proto(proto_response)
390
+
327
391
  def add_modifier(self, modifier: Modifier) -> None:
328
392
  """Add a modifier to the private list"""
329
393
  self._modifiers.append(modifier)
@@ -383,6 +447,7 @@ class ActionClient:
383
447
  query_params: Optional[Dict[str, Any]] = None,
384
448
  body: Optional[Any] = None,
385
449
  form_data: Optional[Dict[str, Any]] = None,
450
+ raw_body: Optional[Union[bytes, str]] = None,
386
451
  headers: Optional[Dict[str, str]] = None,
387
452
  **kwargs,
388
453
  ) -> requests.Response:
@@ -403,6 +468,14 @@ class ActionClient:
403
468
  :type body: Optional[Any]
404
469
  :param form_data: Request body sent as URL-encoded form data
405
470
  :type form_data: Optional[Dict[str, Any]]
471
+ :param raw_body: Raw request body sent as-is, without any serialization.
472
+ Use this **only** when the request payload is not JSON — for example,
473
+ when the downstream API expects an XML body, a plain-text payload, or
474
+ any other non-JSON content type. For JSON payloads use ``body`` instead.
475
+ When ``raw_body`` is provided it takes priority over both ``body`` and
476
+ ``form_data``. You must also pass a matching ``Content-Type`` header via
477
+ ``headers`` (e.g. ``"Content-Type": "application/xml"``).
478
+ :type raw_body: Optional[Union[bytes, str]]
406
479
  :param headers: Additional HTTP headers to merge into the request
407
480
  :type headers: Optional[Dict[str, str]]
408
481
 
@@ -439,8 +512,8 @@ class ActionClient:
439
512
  method=method.upper(),
440
513
  url=url,
441
514
  params=params,
442
- json=body,
443
- data=form_data,
515
+ json=body if raw_body is None else None,
516
+ data=raw_body or form_data,
444
517
  headers=req_headers,
445
518
  timeout=timeout,
446
519
  **kwargs,
@@ -454,8 +527,8 @@ class ActionClient:
454
527
  method=method.upper(),
455
528
  url=url,
456
529
  params=params,
457
- json=body,
458
- data=form_data,
530
+ json=body if raw_body is None else None,
531
+ data=raw_body if raw_body is not None else form_data,
459
532
  headers=req_headers,
460
533
  timeout=timeout,
461
534
  **kwargs,
@@ -1086,3 +1159,116 @@ class ActionMcp:
1086
1159
  include_auth_links=include_auth_links,
1087
1160
  )
1088
1161
  return GetMcpInstanceAuthStateResponse.from_proto(result_tuple[0])
1162
+
1163
+
1164
+ class ActionProviders:
1165
+ """Typed action layer over ProvidersClient for custom provider CRUD.
1166
+
1167
+ Accepts typed request objects and returns typed response objects.
1168
+ Access via ActionClient.providers — do not instantiate directly.
1169
+ """
1170
+
1171
+ def __init__(self, providers_client) -> None:
1172
+ self._providers_client = providers_client
1173
+
1174
+ def create_custom_provider(
1175
+ self,
1176
+ request: CreateCustomProviderRequest,
1177
+ ) -> CreateCustomProviderResponse:
1178
+ """Create a new custom provider.
1179
+
1180
+ :param request: Request object containing display_name (required),
1181
+ proxy_url (required), and optional description,
1182
+ proxy_enabled, and auth_patterns.
1183
+ :type request: CreateCustomProviderRequest
1184
+
1185
+ :returns: Response containing the created provider with its server-assigned
1186
+ identifier and all decoded auth_patterns.
1187
+ :rtype: CreateCustomProviderResponse
1188
+
1189
+ :raises ScalekitBadRequestException: If required fields are missing or invalid.
1190
+ :raises ScalekitConflictException: If a provider with the same name already exists.
1191
+ """
1192
+ result_tuple = self._providers_client.create_custom_provider(
1193
+ display_name=request.display_name,
1194
+ proxy_url=request.proxy_url,
1195
+ proxy_enabled=request.proxy_enabled,
1196
+ description=request.description,
1197
+ auth_patterns=request.auth_patterns,
1198
+ )
1199
+ return CreateCustomProviderResponse.from_proto(result_tuple[0])
1200
+
1201
+ def update_custom_provider(
1202
+ self,
1203
+ request: UpdateCustomProviderRequest,
1204
+ ) -> UpdateCustomProviderResponse:
1205
+ """Update an existing custom provider.
1206
+
1207
+ Only fields set to a non-None value in the request are applied.
1208
+ Fields left as None are ignored and their existing server values are kept.
1209
+
1210
+ :param request: Request object containing identifier (required) and any
1211
+ combination of display_name, description, proxy_url, and
1212
+ auth_patterns to update.
1213
+ :type request: UpdateCustomProviderRequest
1214
+
1215
+ :returns: Response containing the provider's full state after the update.
1216
+ :rtype: UpdateCustomProviderResponse
1217
+
1218
+ :raises ScalekitNotFoundException: If no provider with the given identifier exists.
1219
+ :raises ScalekitBadRequestException: If any updated field value is invalid.
1220
+ """
1221
+ result_tuple = self._providers_client.update_custom_provider(
1222
+ identifier=request.identifier,
1223
+ display_name=request.display_name,
1224
+ proxy_url=request.proxy_url,
1225
+ description=request.description,
1226
+ auth_patterns=request.auth_patterns,
1227
+ )
1228
+ return UpdateCustomProviderResponse.from_proto(result_tuple[0])
1229
+
1230
+ def list_providers(
1231
+ self,
1232
+ request: ListProvidersRequest,
1233
+ ) -> ListProvidersResponse:
1234
+ """List providers with optional filtering and pagination.
1235
+
1236
+ :param request: Request object with optional provider_type, page_size,
1237
+ page_token, and identifier filters. All fields are optional —
1238
+ an empty ListProvidersRequest() returns all providers.
1239
+ :type request: ListProvidersRequest
1240
+
1241
+ :returns: Response containing a page of providers and a next_page_token
1242
+ for fetching subsequent pages.
1243
+ :rtype: ListProvidersResponse
1244
+ """
1245
+ result_tuple = self._providers_client.list_providers(
1246
+ page_size=request.page_size,
1247
+ page_token=request.page_token,
1248
+ provider_type=request.provider_type,
1249
+ identifier=request.identifier,
1250
+ )
1251
+ return ListProvidersResponse.from_proto(result_tuple[0])
1252
+
1253
+ def delete_custom_provider(
1254
+ self,
1255
+ request: DeleteCustomProviderRequest,
1256
+ ) -> DeleteCustomProviderResponse:
1257
+ """Delete a custom provider by identifier.
1258
+
1259
+ Deletion is permanent. Returns an empty response on success. Any error
1260
+ (provider not found, insufficient permissions) raises a
1261
+ ScalekitServerException subclass before this method returns.
1262
+
1263
+ :param request: Request object containing the identifier of the provider
1264
+ to delete.
1265
+ :type request: DeleteCustomProviderRequest
1266
+
1267
+ :returns: Empty response confirming deletion.
1268
+ :rtype: DeleteCustomProviderResponse
1269
+
1270
+ :raises ScalekitNotFoundException: If no provider with the given identifier exists.
1271
+ :raises ScalekitForbiddenException: If the caller lacks permission to delete.
1272
+ """
1273
+ result_tuple = self._providers_client.delete_custom_provider(request.identifier)
1274
+ return DeleteCustomProviderResponse.from_proto(result_tuple[0])
@@ -0,0 +1,348 @@
1
+ from typing import List, Literal, Optional
2
+
3
+ from google.protobuf.json_format import MessageToDict
4
+ from pydantic import BaseModel, Field, root_validator
5
+
6
+
7
+ class AuthField(BaseModel):
8
+ """A single credential input field displayed to the user during connection setup.
9
+
10
+ AuthField is only used with BEARER and API_KEY auth patterns — do not attach
11
+ fields to OAUTH patterns (the OAuth flow collects credentials itself).
12
+
13
+ Use one AuthField per credential the user must supply. For a BEARER connector, add one AuthField(field_name='token', ...). For an
14
+ API_KEY connector, add one AuthField(field_name='api_key',
15
+ ...). Always set input_type='password' for tokens and keys so the UI masks the
16
+ value.
17
+ """
18
+
19
+ field_name: str = Field(
20
+ ...,
21
+ description=(
22
+ "Required. Machine-readable identifier for this field. Used as the key "
23
+ "when the credential value is stored and retrieved. "
24
+ "For BEARER patterns use 'token' or 'bearer_token'. "
25
+ "For API_KEY patterns use 'api_key'."
26
+ ),
27
+ )
28
+ label: str = Field(
29
+ "",
30
+ description=(
31
+ "Optional. Human-readable label displayed above the input in the UI. "
32
+ "Example: 'API Key', 'Bearer Token'. Defaults to empty string."
33
+ ),
34
+ )
35
+ input_type: Literal["text", "password"] = Field(
36
+ "text",
37
+ description=(
38
+ "Optional. Controls how the input is rendered in the UI. "
39
+ "Accepted values: 'text' (visible input, default) or "
40
+ "'password' (masked input — use for secrets, tokens, and keys)."
41
+ ),
42
+ )
43
+ hint: str = Field(
44
+ "",
45
+ description=(
46
+ "Optional. Placeholder or helper text shown below the input field. "
47
+ "Example: 'Find your token at Settings → API'. Defaults to empty string."
48
+ ),
49
+ )
50
+ required: bool = Field(
51
+ False,
52
+ description=(
53
+ "Optional. Whether the user must fill this field before the connection "
54
+ "can be saved. True = field is mandatory; False = field is optional. "
55
+ "Defaults to False."
56
+ ),
57
+ )
58
+
59
+ def to_dict(self) -> dict:
60
+ """Serialize this field to a wire-format dict for inclusion in auth_patterns.
61
+
62
+ :returns: Dict representation of the field. 'hint' and 'required' are omitted
63
+ when they hold their default values to keep the wire payload minimal.
64
+ :rtype: dict
65
+ """
66
+ d: dict = {
67
+ "field_name": self.field_name,
68
+ "label": self.label,
69
+ "input_type": self.input_type,
70
+ }
71
+ if self.hint:
72
+ d["hint"] = self.hint
73
+ if self.required:
74
+ d["required"] = True
75
+ return d
76
+
77
+ @classmethod
78
+ def from_dict(cls, d: dict) -> "AuthField":
79
+ """Deserialize an AuthField from a response dict.
80
+
81
+ :param d: Dict containing field data as returned by the server.
82
+ :type d: dict
83
+ :returns: AuthField instance populated from the dict values.
84
+ :rtype: AuthField
85
+ """
86
+ return cls(
87
+ field_name=d.get("field_name", ""),
88
+ label=d.get("label", ""),
89
+ input_type=d.get("input_type", "text"),
90
+ hint=d.get("hint", ""),
91
+ required=d.get("required", False),
92
+ )
93
+
94
+
95
+ class OAuthConfig(BaseModel):
96
+ """OAuth configuration attached to an OAUTH auth pattern.
97
+
98
+ Pass OAuthConfig() (all defaults) for MCP connectors that use Dynamic Client
99
+ Registration — the MCP server manages the OAuth flow itself and no static
100
+ endpoints are needed. Set pkce_enabled=False only if your OAuth server does
101
+ not support PKCE.
102
+
103
+ This class is only used with AuthPattern(type="OAUTH"). Do not attach it to
104
+ BEARER or API_KEY patterns.
105
+ """
106
+
107
+ pkce_enabled: bool = Field(
108
+ True,
109
+ description=(
110
+ "Optional. Whether to enable PKCE (Proof Key for Code Exchange, RFC 7636) "
111
+ "for the OAuth authorization flow. True = PKCE on (default, recommended); "
112
+ "False = PKCE disabled. Only set to False if the OAuth server does not "
113
+ "support PKCE."
114
+ ),
115
+ )
116
+
117
+ def to_dict(self) -> dict:
118
+ """Serialize to a wire-format dict.
119
+
120
+ :returns: Dict with a single key 'pkce_enabled'. Always emitted explicitly
121
+ so the server receives an unambiguous value.
122
+ :rtype: dict
123
+ """
124
+ return {"pkce_enabled": self.pkce_enabled}
125
+
126
+ @classmethod
127
+ def from_dict(cls, d: dict) -> "OAuthConfig":
128
+ """Deserialize an OAuthConfig from a response dict.
129
+
130
+ :param d: Dict containing oauth_config data as returned by the server.
131
+ :type d: dict
132
+ :returns: OAuthConfig instance. pkce_enabled defaults to True if the key
133
+ is absent from the dict.
134
+ :rtype: OAuthConfig
135
+ """
136
+ return cls(pkce_enabled=d.get("pkce_enabled", True))
137
+
138
+
139
+ class AuthPattern(BaseModel):
140
+ """One authentication option available on a custom connector.
141
+
142
+ A custom provider can have multiple auth patterns (e.g. both OAUTH and API_KEY),
143
+ giving users a choice of how to authenticate. For MCP connectors set is_mcp=True
144
+ on every pattern.
145
+
146
+ Type guide:
147
+ - "OAUTH" — Browser-based OAuth 2.0 / 2.1 flow. Attach an OAuthConfig.
148
+ - "BEARER" — Static bearer token supplied by the user. Add AuthFields for
149
+ the token input.
150
+ - "API_KEY" — Static API key supplied by the user. Add AuthFields for the
151
+ key input.
152
+ """
153
+
154
+ type: Literal["OAUTH", "BEARER", "API_KEY"] = Field(
155
+ ...,
156
+ description=(
157
+ "Required. Authentication mechanism for this pattern. "
158
+ "Accepted values: 'OAUTH' (browser OAuth flow), "
159
+ "'BEARER' (static bearer token), 'API_KEY' (static API key)."
160
+ ),
161
+ )
162
+ display_name: str = Field(
163
+ ...,
164
+ description=(
165
+ "Required. Human-readable label for this auth option shown in the UI. "
166
+ "Accepted characters: a-z, A-Z, 0-9, and spaces. "
167
+ "Example: 'GitHub OAuth', 'API Token', 'Service Account Key'."
168
+ ),
169
+ )
170
+ description: str = Field(
171
+ "",
172
+ description=(
173
+ "Optional. Short explanation of this auth method shown to the user. "
174
+ "Example: 'Authenticate with your GitHub account using OAuth 2.1'. "
175
+ "Defaults to empty string."
176
+ ),
177
+ )
178
+ fields: List[AuthField] = Field(
179
+ default_factory=list,
180
+ description=(
181
+ "Optional. List of AuthField objects defining the credential inputs "
182
+ "the user must supply. Only applicable to BEARER and API_KEY types — "
183
+ "must be empty (or omitted) for OAUTH, which collects credentials "
184
+ "through the browser OAuth flow and does not use static input fields. "
185
+ "Defaults to empty list."
186
+ ),
187
+ )
188
+ is_mcp: bool = Field(
189
+ False,
190
+ description=(
191
+ "Optional. Set to True for MCP (Model Context Protocol) server connectors. "
192
+ "When True the server sets is_custom_mcp=True on the provider. "
193
+ "Defaults to False."
194
+ ),
195
+ )
196
+ oauth_config: Optional["OAuthConfig"] = Field(
197
+ None,
198
+ description=(
199
+ "Optional. OAuth configuration. Required when type='OAUTH'; omit for "
200
+ "'BEARER' and 'API_KEY' (must be None). "
201
+ "Pass OAuthConfig() for MCP connectors using Dynamic Client Registration. "
202
+ "Pass OAuthConfig(pkce_enabled=False) to disable PKCE. "
203
+ "Defaults to None."
204
+ ),
205
+ )
206
+
207
+ @root_validator(skip_on_failure=True)
208
+ def validate_auth_invariants(cls, values):
209
+ auth_type = values.get("type")
210
+ if auth_type is None:
211
+ return values # type field already failed validation
212
+ oauth_config = values.get("oauth_config")
213
+ fields = values.get("fields", [])
214
+ if auth_type == "OAUTH":
215
+ if oauth_config is None:
216
+ raise ValueError("oauth_config is required when type='OAUTH'")
217
+ if fields:
218
+ raise ValueError("fields must be empty when type='OAUTH'")
219
+ else:
220
+ if oauth_config is not None:
221
+ raise ValueError(f"oauth_config must be None when type='{auth_type}'")
222
+ return values
223
+
224
+ def to_dict(self) -> dict:
225
+ """Serialize to a wire-format dict for inclusion in the auth_patterns ListValue.
226
+
227
+ :returns: Dict representation of this auth pattern. 'description' is omitted
228
+ when empty, 'is_mcp' when False, and 'oauth_config' when None, to
229
+ keep the wire payload minimal.
230
+ :rtype: dict
231
+ """
232
+ d: dict = {
233
+ "type": self.type,
234
+ "display_name": self.display_name,
235
+ "fields": [f.to_dict() for f in self.fields],
236
+ }
237
+ if self.description:
238
+ d["description"] = self.description
239
+ if self.is_mcp:
240
+ d["is_mcp"] = True
241
+ if self.oauth_config is not None:
242
+ d["oauth_config"] = self.oauth_config.to_dict()
243
+ return d
244
+
245
+ @classmethod
246
+ def from_dict(cls, d: dict) -> "AuthPattern":
247
+ """Deserialize an AuthPattern from a response dict.
248
+
249
+ :param d: Dict containing auth pattern data as returned by the server.
250
+ The 'oauth_config' key must be present for OAuth patterns;
251
+ its absence is interpreted as oauth_config=None (non-OAuth).
252
+ :type d: dict
253
+ :returns: AuthPattern instance populated from the dict values.
254
+ :rtype: AuthPattern
255
+ """
256
+ oauth_cfg: Optional[OAuthConfig] = None
257
+ if "oauth_config" in d:
258
+ oauth_cfg = OAuthConfig.from_dict(d["oauth_config"])
259
+ return cls(
260
+ type=d.get("type", ""),
261
+ display_name=d.get("display_name", ""),
262
+ description=d.get("description", ""),
263
+ fields=[AuthField.from_dict(f) for f in d.get("fields", [])],
264
+ is_mcp=d.get("is_mcp", False),
265
+ oauth_config=oauth_cfg,
266
+ )
267
+
268
+ class Config:
269
+ validate_assignment = True
270
+
271
+
272
+ class Provider(BaseModel):
273
+ """A custom provider as returned by the Scalekit API.
274
+
275
+ Produced exclusively by ProvidersClient response decoding via from_proto().
276
+ All fields are populated from the server response — do not construct this
277
+ directly. The auth_patterns list is fully decoded so callers never need to
278
+ handle protobuf types.
279
+ """
280
+
281
+ identifier: str = Field(
282
+ "",
283
+ description="Unique identifier assigned by the server. Read-only.",
284
+ )
285
+ display_name: str = Field(
286
+ "",
287
+ description=(
288
+ "Human-readable name of the provider. "
289
+ "Accepted characters: a-z, A-Z, 0-9, and spaces."
290
+ ),
291
+ )
292
+ description: str = Field(
293
+ "",
294
+ description="Short description of the provider.",
295
+ )
296
+ proxy_url: str = Field(
297
+ "",
298
+ description="The proxy URL through which requests to this provider are routed.",
299
+ )
300
+ proxy_enabled: bool = Field(
301
+ False,
302
+ description="Whether request proxying is enabled for this provider.",
303
+ )
304
+ is_custom: bool = Field(
305
+ False,
306
+ description="True for all providers created via create_custom_provider.",
307
+ )
308
+ is_custom_mcp: bool = Field(
309
+ False,
310
+ description=(
311
+ "True when at least one auth_pattern was created with is_mcp=True. "
312
+ "Set by the server — not a field you write."
313
+ ),
314
+ )
315
+ auth_patterns: List[AuthPattern] = Field(
316
+ default_factory=list,
317
+ description=(
318
+ "Decoded list of authentication options for this provider. "
319
+ "Currently contains at most one element — only a single auth pattern "
320
+ "is supported today. The list type is intentional for future multi-pattern support."
321
+ ),
322
+ )
323
+
324
+ @classmethod
325
+ def from_proto(cls, proto) -> "Provider":
326
+ """Decode a proto Provider message into a typed Provider.
327
+
328
+ Calls MessageToDict on the auth_patterns ListValue field to produce a
329
+ plain Python list, then deserializes each element into an AuthPattern.
330
+
331
+ :param proto: A proto Provider message instance from providers_pb2.
332
+ :returns: Provider instance with all fields populated and auth_patterns decoded.
333
+ :rtype: Provider
334
+ """
335
+ auth_patterns_raw = MessageToDict(proto.auth_patterns)
336
+ return cls(
337
+ identifier=proto.identifier,
338
+ display_name=proto.display_name,
339
+ description=proto.description,
340
+ proxy_url=proto.proxy_url,
341
+ proxy_enabled=proto.proxy_enabled,
342
+ is_custom=proto.is_custom,
343
+ is_custom_mcp=proto.is_custom_mcp,
344
+ auth_patterns=[AuthPattern.from_dict(p) for p in auth_patterns_raw],
345
+ )
346
+
347
+ class Config:
348
+ validate_assignment = True
@@ -4,7 +4,8 @@ from scalekit.v1.connected_accounts.connected_accounts_pb2 import (
4
4
  CreateConnectedAccount,
5
5
  AuthorizationDetails,
6
6
  OauthToken,
7
- StaticAuth
7
+ StaticAuth,
8
+ GoogleDWDAuth
8
9
  )
9
10
  from google.protobuf import struct_pb2
10
11
 
@@ -44,6 +45,16 @@ class CreateConnectedAccountRequest(BaseModel):
44
45
  struct_details.update(static_data)
45
46
  static_auth = StaticAuth(details=struct_details)
46
47
  auth_details = AuthorizationDetails(static_auth=static_auth)
48
+
49
+ elif self.authorization_details and "google_dwd" in self.authorization_details:
50
+ dwd_data = self.authorization_details["google_dwd"]
51
+ if not isinstance(dwd_data, dict):
52
+ raise ValueError("authorization_details.google_dwd must be an object")
53
+ subject = dwd_data.get("subject")
54
+ if not subject:
55
+ raise ValueError("authorization_details.google_dwd.subject is required")
56
+ google_dwd = GoogleDWDAuth(subject=subject)
57
+ auth_details = AuthorizationDetails(google_dwd=google_dwd)
47
58
 
48
59
  # Handle api_config if provided
49
60
  api_config_struct = None
@@ -58,4 +69,4 @@ class CreateConnectedAccountRequest(BaseModel):
58
69
 
59
70
  class Config:
60
71
  """Pydantic configuration"""
61
- validate_assignment = True
72
+ validate_assignment = True