ergon-framework-python 0.2.0__tar.gz → 0.2.2__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 (124) hide show
  1. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/PKG-INFO +3 -3
  2. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/pyproject.toml +3 -3
  3. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/__init__.py +1 -1
  4. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/__init__.py +20 -0
  5. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/__init__.py +110 -0
  6. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/async_connector.py +5 -0
  7. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/__init__.py +54 -0
  8. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/adapters.py +230 -0
  9. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/async_connector.py +327 -0
  10. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/connector.py +294 -0
  11. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/models.py +460 -0
  12. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/services/__init__.py +39 -0
  13. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/services/activity.py +300 -0
  14. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/services/addresses.py +325 -0
  15. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/services/attachments.py +283 -0
  16. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/services/messages.py +127 -0
  17. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/services/records.py +75 -0
  18. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/channels/services/service.py +34 -0
  19. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/connector.py +5 -0
  20. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/models.py +35 -0
  21. ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/utils.py +41 -0
  22. {ergon_framework_python-0.2.0/src/ergon/connector/ergon_platform → ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/workflows}/__init__.py +12 -3
  23. {ergon_framework_python-0.2.0/src/ergon/connector/ergon_platform → ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/workflows}/_operations.py +8 -3
  24. {ergon_framework_python-0.2.0/src/ergon/connector/ergon_platform → ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/workflows}/async_connector.py +7 -6
  25. {ergon_framework_python-0.2.0/src/ergon/connector/ergon_platform → ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/workflows}/connector.py +7 -6
  26. {ergon_framework_python-0.2.0/src/ergon/connector/ergon_platform → ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/workflows}/models.py +0 -17
  27. {ergon_framework_python-0.2.0/src/ergon/connector/ergon_platform → ergon_framework_python-0.2.2/src/ergon/connector/ergon_platform/workflows}/utils.py +1 -1
  28. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/async_connector.py +6 -0
  29. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/async_service.py +3 -0
  30. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/connector.py +6 -0
  31. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/models.py +8 -0
  32. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/service.py +9 -0
  33. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/utils.py +2 -4
  34. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/mixins/consumer.py +0 -2
  35. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon_framework_python.egg-info/PKG-INFO +3 -3
  36. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon_framework_python.egg-info/SOURCES.txt +18 -1
  37. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon_framework_python.egg-info/requires.txt +2 -2
  38. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/tests/test_smoke.py +1 -1
  39. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/LICENSE +0 -0
  40. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/README.md +0 -0
  41. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/setup.cfg +0 -0
  42. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/__init__.py +0 -0
  43. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/_observability/docker-compose.telemetry.yml +0 -0
  44. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/_observability/grafana.yaml +0 -0
  45. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/_observability/loki.yaml +0 -0
  46. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/_observability/otel-collector-config.yaml +0 -0
  47. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/_observability/prometheus.yaml +0 -0
  48. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/_observability/tempo.yaml +0 -0
  49. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/connectors/__init__.py +0 -0
  50. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/main.py +0 -0
  51. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/__init__.py +0 -0
  52. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/constants.py +0 -0
  53. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/example_task/__init__.py +0 -0
  54. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/example_task/config.py +0 -0
  55. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/example_task/exceptions.py +0 -0
  56. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/example_task/helpers.py +0 -0
  57. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/example_task/schemas.py +0 -0
  58. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/example_task/task.py +0 -0
  59. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/exceptions.py +0 -0
  60. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/helpers.py +0 -0
  61. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/schemas.py +0 -0
  62. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/bootstrap/src/__project__/tasks/settings.py +0 -0
  63. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/cli.py +0 -0
  64. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/_lazy.py +0 -0
  65. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/connector.py +0 -0
  66. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/ergon_platform/_client.py +0 -0
  67. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/excel/__init__.py +0 -0
  68. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/excel/connector.py +0 -0
  69. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/excel/models.py +0 -0
  70. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/excel/service.py +0 -0
  71. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/__init__.py +0 -0
  72. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/async_auth_service.py +0 -0
  73. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/nylas/auth_service.py +0 -0
  74. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/pipefy/__init__.py +0 -0
  75. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/pipefy/async_connector.py +0 -0
  76. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/pipefy/async_service.py +0 -0
  77. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/pipefy/connector.py +0 -0
  78. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/pipefy/models.py +0 -0
  79. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/pipefy/service.py +0 -0
  80. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/pipefy/version.py +0 -0
  81. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/postgres/__init__.py +0 -0
  82. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/postgres/async_connector.py +0 -0
  83. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/postgres/async_service.py +0 -0
  84. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/postgres/models.py +0 -0
  85. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/rabbitmq/__init__.py +0 -0
  86. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/rabbitmq/async_connector.py +0 -0
  87. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/rabbitmq/async_service.py +0 -0
  88. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/rabbitmq/connector.py +0 -0
  89. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/rabbitmq/helper.py +0 -0
  90. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/rabbitmq/models.py +0 -0
  91. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/rabbitmq/service.py +0 -0
  92. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/sqs/__init__.py +0 -0
  93. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/sqs/async_connector.py +0 -0
  94. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/sqs/async_service.py +0 -0
  95. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/sqs/connector.py +0 -0
  96. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/sqs/models.py +0 -0
  97. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/sqs/service.py +0 -0
  98. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/connector/transaction.py +0 -0
  99. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/py.typed +0 -0
  100. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/service/__init__.py +0 -0
  101. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/service/service.py +0 -0
  102. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/__init__.py +0 -0
  103. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/base.py +0 -0
  104. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/exceptions.py +0 -0
  105. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/helpers.py +0 -0
  106. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/liveness.py +0 -0
  107. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/manager.py +0 -0
  108. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/mixins/__init__.py +0 -0
  109. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/mixins/metrics.py +0 -0
  110. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/mixins/producer.py +0 -0
  111. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/policies.py +0 -0
  112. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/runner.py +0 -0
  113. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/task/utils.py +0 -0
  114. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/telemetry/__init__.py +0 -0
  115. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/telemetry/_resource.py +0 -0
  116. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/telemetry/logging.py +0 -0
  117. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/telemetry/metrics.py +0 -0
  118. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/telemetry/tracing.py +0 -0
  119. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/utils/__init__.py +0 -0
  120. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon/utils/env.py +0 -0
  121. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon_framework_python.egg-info/dependency_links.txt +0 -0
  122. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon_framework_python.egg-info/entry_points.txt +0 -0
  123. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/src/ergon_framework_python.egg-info/top_level.txt +0 -0
  124. {ergon_framework_python-0.2.0 → ergon_framework_python-0.2.2}/tests/test_optional_connectors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ergon-framework-python
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Ergon internal task-oriented project bootstrapper
5
5
  Author-email: Ergondata Technologies <anza.vossos@protonmail.com>
6
6
  License-Expression: MIT
@@ -29,14 +29,14 @@ Requires-Dist: aio-pika>=9.0.0; extra == "all"
29
29
  Requires-Dist: aiobotocore>=2.13.0; extra == "all"
30
30
  Requires-Dist: asyncpg>=0.29.0; extra == "all"
31
31
  Requires-Dist: boto3>=1.35.0; extra == "all"
32
- Requires-Dist: ergon-platform-sdk>=0.1.0; extra == "all"
32
+ Requires-Dist: ergon-platform-sdk>=0.2.0; extra == "all"
33
33
  Requires-Dist: httpx>=0.28.0; extra == "all"
34
34
  Requires-Dist: nylas>=6.0.0; extra == "all"
35
35
  Requires-Dist: openpyxl>=3.1.5; extra == "all"
36
36
  Requires-Dist: pika>=1.3.0; extra == "all"
37
37
  Requires-Dist: requests>=2.32.5; extra == "all"
38
38
  Provides-Extra: ergon-platform
39
- Requires-Dist: ergon-platform-sdk>=0.1.0; extra == "ergon-platform"
39
+ Requires-Dist: ergon-platform-sdk>=0.2.0; extra == "ergon-platform"
40
40
  Requires-Dist: httpx>=0.28.0; extra == "ergon-platform"
41
41
  Provides-Extra: excel
42
42
  Requires-Dist: openpyxl>=3.1.5; extra == "excel"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ergon-framework-python"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "Ergon internal task-oriented project bootstrapper"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -34,7 +34,7 @@ all = [
34
34
  "aiobotocore>=2.13.0",
35
35
  "asyncpg>=0.29.0",
36
36
  "boto3>=1.35.0",
37
- "ergon-platform-sdk>=0.1.0",
37
+ "ergon-platform-sdk>=0.2.0",
38
38
  "httpx>=0.28.0",
39
39
  "nylas>=6.0.0",
40
40
  "openpyxl>=3.1.5",
@@ -42,7 +42,7 @@ all = [
42
42
  "requests>=2.32.5",
43
43
  ]
44
44
  "ergon-platform" = [
45
- "ergon-platform-sdk>=0.1.0",
45
+ "ergon-platform-sdk>=0.2.0",
46
46
  "httpx>=0.28.0",
47
47
  ]
48
48
  excel = ["openpyxl>=3.1.5"]
@@ -10,4 +10,4 @@ __all__ = [
10
10
  "manager",
11
11
  ]
12
12
 
13
- __version__ = "0.2.0"
13
+ __version__ = "0.2.2"
@@ -7,13 +7,23 @@ from .transaction import Transaction
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from .ergon_platform import (
10
+ AsyncErgonPlatformChannelsConnector,
10
11
  AsyncErgonPlatformConnector,
11
12
  CreateItemInput,
13
+ ErgonPlatformChannelsConfig,
14
+ ErgonPlatformChannelsConnector,
15
+ ErgonPlatformChannelsConsumerConfig,
16
+ ErgonPlatformChannelsProducerConfig,
12
17
  ErgonPlatformClient,
13
18
  ErgonPlatformConnector,
14
19
  ErgonPlatformConsumerConfig,
15
20
  ErgonPlatformProducerConfig,
16
21
  )
22
+
23
+ # NOTE: ``SendMessageInput`` is defined by both Nylas and Channels with
24
+ # different shapes. The top-level alias here points to the Nylas type
25
+ # (matches the pre-split lazy-export map); channels users must import it
26
+ # from ``ergon.connector.ergon_platform.channels``.
17
27
  from .excel import ExcelConnector, ExcelFetchConfig, ExcelRow, ExcelService
18
28
  from .nylas import (
19
29
  AckActionConfig,
@@ -76,6 +86,7 @@ _CONNECTOR_SUBPACKAGES = (
76
86
 
77
87
  _LAZY_EXPORTS = {
78
88
  "AckActionConfig": "nylas",
89
+ "AsyncErgonPlatformChannelsConnector": "ergon_platform",
79
90
  "AsyncErgonPlatformConnector": "ergon_platform",
80
91
  "AsyncNylasAuthService": "nylas",
81
92
  "AsyncNylasConnector": "nylas",
@@ -94,6 +105,10 @@ _LAZY_EXPORTS = {
94
105
  "AuthUrlConfig": "nylas",
95
106
  "CodeExchangeInput": "nylas",
96
107
  "CreateItemInput": "ergon_platform",
108
+ "ErgonPlatformChannelsConfig": "ergon_platform",
109
+ "ErgonPlatformChannelsConnector": "ergon_platform",
110
+ "ErgonPlatformChannelsConsumerConfig": "ergon_platform",
111
+ "ErgonPlatformChannelsProducerConfig": "ergon_platform",
97
112
  "ErgonPlatformClient": "ergon_platform",
98
113
  "ErgonPlatformConnector": "ergon_platform",
99
114
  "ErgonPlatformConsumerConfig": "ergon_platform",
@@ -148,6 +163,7 @@ def __dir__() -> list[str]:
148
163
  __all__ = [
149
164
  "AckActionConfig",
150
165
  "AsyncConnector",
166
+ "AsyncErgonPlatformChannelsConnector",
151
167
  "AsyncErgonPlatformConnector",
152
168
  "AsyncNylasAuthService",
153
169
  "AsyncNylasConnector",
@@ -169,6 +185,10 @@ __all__ = [
169
185
  "Connector",
170
186
  "ConnectorConfig",
171
187
  "CreateItemInput",
188
+ "ErgonPlatformChannelsConfig",
189
+ "ErgonPlatformChannelsConnector",
190
+ "ErgonPlatformChannelsConsumerConfig",
191
+ "ErgonPlatformChannelsProducerConfig",
172
192
  "ErgonPlatformClient",
173
193
  "ErgonPlatformConnector",
174
194
  "ErgonPlatformConsumerConfig",
@@ -0,0 +1,110 @@
1
+ """Ergon Platform connectors — Workflows and Channels.
2
+
3
+ The Ergon Platform SDK exposes several services (workflows, channels, agents,
4
+ buckets, ...). This package groups every framework connector against that
5
+ platform. Each service lives in its own sub-package (``workflows``,
6
+ ``channels``, ...) and reuses the shared credentials model
7
+ (:class:`ErgonPlatformClient`) so a single API key drives every connector.
8
+
9
+ Public workflow names are re-exported here for backward compatibility with the
10
+ pre-split layout::
11
+
12
+ from ergon.connector.ergon_platform import ErgonPlatformConnector # workflows
13
+
14
+ New code is encouraged to import directly from the sub-package::
15
+
16
+ from ergon.connector.ergon_platform.workflows import ErgonPlatformConnector
17
+ from ergon.connector.ergon_platform.channels import ErgonPlatformChannelsConnector
18
+ """
19
+
20
+ from importlib import import_module
21
+ from typing import TYPE_CHECKING, Any
22
+
23
+ from .._lazy import exported_names, load_optional_export
24
+ from .models import ErgonPlatformClient
25
+
26
+ if TYPE_CHECKING:
27
+ from .channels import (
28
+ AsyncErgonPlatformChannelsConnector,
29
+ ErgonPlatformChannelsConfig,
30
+ ErgonPlatformChannelsConnector,
31
+ ErgonPlatformChannelsConsumerConfig,
32
+ ErgonPlatformChannelsProducerConfig,
33
+ ErgonPlatformChannelsService,
34
+ SendMessageInput,
35
+ SendMessagePayload,
36
+ )
37
+ from .workflows import (
38
+ AsyncErgonPlatformConnector,
39
+ CreateItemInput,
40
+ CreateItemPayload,
41
+ ErgonPlatformConnector,
42
+ ErgonPlatformConsumerConfig,
43
+ ErgonPlatformProducerConfig,
44
+ ErgonPlatformWorkflowsService,
45
+ )
46
+
47
+ _SUBPACKAGES = ("channels", "workflows")
48
+
49
+ # Backward-compat aliases: names that used to live under
50
+ # ``ergon.connector.ergon_platform`` before the workflows/ split, plus the new
51
+ # channels API surface. Every entry is loaded lazily from its sub-package to
52
+ # keep the platform SDK out of the core import path.
53
+ _LAZY_EXPORTS = {
54
+ # Workflows (pre-split names — kept for backward compatibility)
55
+ "AsyncErgonPlatformConnector": "workflows",
56
+ "CreateItemInput": "workflows",
57
+ "CreateItemPayload": "workflows",
58
+ "ErgonPlatformConnector": "workflows",
59
+ "ErgonPlatformConsumerConfig": "workflows",
60
+ "ErgonPlatformProducerConfig": "workflows",
61
+ "ErgonPlatformWorkflowsService": "workflows",
62
+ # Channels
63
+ "AsyncErgonPlatformChannelsConnector": "channels",
64
+ "ErgonPlatformChannelsConfig": "channels",
65
+ "ErgonPlatformChannelsConnector": "channels",
66
+ "ErgonPlatformChannelsConsumerConfig": "channels",
67
+ "ErgonPlatformChannelsProducerConfig": "channels",
68
+ "ErgonPlatformChannelsService": "channels",
69
+ "SendMessageInput": "channels",
70
+ "SendMessagePayload": "channels",
71
+ }
72
+
73
+
74
+ def __getattr__(name: str) -> Any:
75
+ if name in _SUBPACKAGES:
76
+ module = import_module(f".{name}", __name__)
77
+ globals()[name] = module
78
+ return module
79
+ return load_optional_export(
80
+ name=name,
81
+ package=__name__,
82
+ exports=_LAZY_EXPORTS,
83
+ namespace=globals(),
84
+ extra="ergon-platform",
85
+ dependencies=("ergon_platform", "httpx"),
86
+ )
87
+
88
+
89
+ def __dir__() -> list[str]:
90
+ return sorted(set(exported_names(globals(), _LAZY_EXPORTS)) | set(_SUBPACKAGES))
91
+
92
+
93
+ __all__ = [
94
+ "AsyncErgonPlatformChannelsConnector",
95
+ "AsyncErgonPlatformConnector",
96
+ "CreateItemInput",
97
+ "CreateItemPayload",
98
+ "ErgonPlatformChannelsConfig",
99
+ "ErgonPlatformChannelsConnector",
100
+ "ErgonPlatformChannelsConsumerConfig",
101
+ "ErgonPlatformChannelsProducerConfig",
102
+ "ErgonPlatformChannelsService",
103
+ "ErgonPlatformClient",
104
+ "ErgonPlatformConnector",
105
+ "ErgonPlatformConsumerConfig",
106
+ "ErgonPlatformProducerConfig",
107
+ "ErgonPlatformWorkflowsService",
108
+ "SendMessageInput",
109
+ "SendMessagePayload",
110
+ ]
@@ -0,0 +1,5 @@
1
+ """Deprecated compatibility import for the async Workflows connector."""
2
+
3
+ from .workflows.async_connector import AsyncErgonPlatformConnector
4
+
5
+ __all__ = ["AsyncErgonPlatformConnector"]
@@ -0,0 +1,54 @@
1
+ from typing import TYPE_CHECKING, Any
2
+
3
+ from ..._lazy import exported_names, load_optional_export
4
+ from .models import (
5
+ ChannelsActivityFilter,
6
+ ErgonPlatformChannelsConfig,
7
+ ErgonPlatformChannelsConsumerConfig,
8
+ ErgonPlatformChannelsProducerConfig,
9
+ InboxAttachmentFile,
10
+ SendMessageAttachment,
11
+ SendMessageInput,
12
+ SendMessagePayload,
13
+ )
14
+
15
+ if TYPE_CHECKING:
16
+ from .async_connector import AsyncErgonPlatformChannelsConnector
17
+ from .connector import ErgonPlatformChannelsConnector
18
+ from .services import ErgonPlatformChannelsService
19
+
20
+ _LAZY_EXPORTS = {
21
+ "AsyncErgonPlatformChannelsConnector": "async_connector",
22
+ "ErgonPlatformChannelsConnector": "connector",
23
+ "ErgonPlatformChannelsService": "services",
24
+ }
25
+
26
+
27
+ def __getattr__(name: str) -> Any:
28
+ return load_optional_export(
29
+ name=name,
30
+ package=__name__,
31
+ exports=_LAZY_EXPORTS,
32
+ namespace=globals(),
33
+ extra="ergon-platform",
34
+ dependencies=("ergon_platform", "httpx"),
35
+ )
36
+
37
+
38
+ def __dir__() -> list[str]:
39
+ return exported_names(globals(), _LAZY_EXPORTS)
40
+
41
+
42
+ __all__ = [
43
+ "AsyncErgonPlatformChannelsConnector",
44
+ "ChannelsActivityFilter",
45
+ "ErgonPlatformChannelsConnector",
46
+ "ErgonPlatformChannelsConfig",
47
+ "ErgonPlatformChannelsConsumerConfig",
48
+ "ErgonPlatformChannelsProducerConfig",
49
+ "ErgonPlatformChannelsService",
50
+ "InboxAttachmentFile",
51
+ "SendMessageAttachment",
52
+ "SendMessageInput",
53
+ "SendMessagePayload",
54
+ ]
@@ -0,0 +1,230 @@
1
+ from typing import Any, Dict, List, Optional
2
+
3
+ from ...transaction import Transaction
4
+ from .models import ErgonPlatformChannelsConsumerConfig
5
+ from .services.records import SdkRecord
6
+
7
+
8
+ class ActivityAdapter:
9
+ """Map Channels activity events into the connector Transaction shape."""
10
+
11
+ _META_KEYS = (
12
+ "event_type",
13
+ "channel",
14
+ "direction",
15
+ "status",
16
+ "thread_id",
17
+ "correlation_id",
18
+ "provider_message_id",
19
+ "subject",
20
+ "from_address",
21
+ "to_addresses",
22
+ "address_id",
23
+ "consumption_status",
24
+ "acked_at",
25
+ "available_at",
26
+ "consumer_id",
27
+ "attempt_count",
28
+ )
29
+ _DELIVERY_KEYS = (
30
+ "subscription_id",
31
+ "lease_token",
32
+ "lease_expires_at",
33
+ "consumer_id",
34
+ "attempt_count",
35
+ )
36
+
37
+ @classmethod
38
+ def to_transaction(cls, event: Any, *, source: str) -> Transaction:
39
+ """To transaction."""
40
+ payload = SdkRecord.serialize(event)
41
+ payload = payload if isinstance(payload, dict) else {"value": payload}
42
+ metadata: Dict[str, Any] = {"source": source}
43
+ for key in cls._META_KEYS:
44
+ value = payload.get(key)
45
+ if value is not None:
46
+ metadata[key] = value
47
+ nested = payload.get("payload")
48
+ if isinstance(nested, dict):
49
+ metadata["message_payload"] = nested
50
+ attachments = cls.public_attachments(nested.get("attachments"))
51
+ if attachments:
52
+ metadata["attachments"] = attachments
53
+ metadata["has_attachment"] = True
54
+ return Transaction(
55
+ id=SdkRecord.first_id(
56
+ payload,
57
+ "id",
58
+ "log_id",
59
+ "message_id",
60
+ "provider_message_id",
61
+ ),
62
+ payload=payload,
63
+ metadata=metadata,
64
+ )
65
+
66
+ @classmethod
67
+ def claimed_transaction(cls, item: Any) -> Transaction:
68
+ """Claimed transaction."""
69
+ claimed = SdkRecord.serialize(item)
70
+ claimed = claimed if isinstance(claimed, dict) else {}
71
+ transaction = cls.to_transaction(
72
+ claimed.get("event"),
73
+ source="config_activity_claim",
74
+ )
75
+ metadata = dict(transaction.metadata or {})
76
+ delivery = claimed.get("delivery")
77
+ if isinstance(delivery, dict):
78
+ metadata["delivery"] = {key: delivery[key] for key in cls._DELIVERY_KEYS if delivery.get(key) is not None}
79
+ return transaction.model_copy(update={"metadata": metadata})
80
+
81
+ @staticmethod
82
+ def delivery(transaction: Transaction) -> Dict[str, Any]:
83
+ """Delivery."""
84
+ metadata = transaction.metadata or {}
85
+ delivery = metadata.get("delivery")
86
+ if not isinstance(delivery, dict):
87
+ raise ValueError("Transaction was not claimed and cannot be acknowledged or nacked")
88
+ if not delivery.get("subscription_id") or not delivery.get("lease_token"):
89
+ raise ValueError("Transaction claim is missing subscription_id or lease_token")
90
+ return delivery
91
+
92
+ @staticmethod
93
+ def belongs_to_address(
94
+ transaction: Transaction,
95
+ address_id: str,
96
+ ) -> bool:
97
+ """Belongs to address."""
98
+ metadata = transaction.metadata or {}
99
+ nested = metadata.get("message_payload")
100
+ if isinstance(nested, dict):
101
+ candidate = nested.get("address_id") or nested.get("channel_address_id")
102
+ if candidate is not None:
103
+ return str(candidate) == address_id
104
+ event = transaction.payload if isinstance(transaction.payload, dict) else {}
105
+ candidate = event.get("address_id") or event.get("channel_address_id")
106
+ if candidate is not None:
107
+ return str(candidate) == address_id
108
+ return True
109
+
110
+ @staticmethod
111
+ def attachment_id(attachment: Any) -> Optional[str]:
112
+ """Attachment id."""
113
+ if not isinstance(attachment, dict):
114
+ return None
115
+ for key in ("id", "resend_attachment_id", "attachment_id"):
116
+ value = attachment.get(key)
117
+ if value:
118
+ return str(value)
119
+ return None
120
+
121
+ @classmethod
122
+ def public_attachment(
123
+ cls,
124
+ item: Any,
125
+ ) -> Optional[Dict[str, Any]]:
126
+ """Public attachment."""
127
+ if not isinstance(item, dict):
128
+ return None
129
+ filename = str(item.get("filename") or item.get("name") or "").strip()
130
+ if not filename:
131
+ return None
132
+ attachment: Dict[str, Any] = {"filename": filename}
133
+ attachment_id = cls.attachment_id(item)
134
+ if attachment_id:
135
+ attachment["id"] = attachment_id
136
+ content_type = item.get("content_type")
137
+ if content_type:
138
+ attachment["content_type"] = content_type
139
+ size = item.get("size")
140
+ if size is not None:
141
+ attachment["size"] = size
142
+ content = item.get("content")
143
+ if isinstance(content, bytes):
144
+ attachment["content"] = content
145
+ return attachment
146
+
147
+ @classmethod
148
+ def public_attachments(cls, items: Any) -> List[Dict[str, Any]]:
149
+ """Public attachments."""
150
+ if not isinstance(items, list):
151
+ return []
152
+ attachments: List[Dict[str, Any]] = []
153
+ for item in items:
154
+ attachment = cls.public_attachment(item)
155
+ if attachment is not None:
156
+ attachments.append(attachment)
157
+ return attachments
158
+
159
+ @classmethod
160
+ def attachments(
161
+ cls,
162
+ transaction: Transaction,
163
+ ) -> List[Dict[str, Any]]:
164
+ """Attachments."""
165
+ metadata = transaction.metadata or {}
166
+ items = metadata.get("attachments")
167
+ if isinstance(items, list):
168
+ return [item for item in items if isinstance(item, dict)]
169
+ nested = metadata.get("message_payload")
170
+ if isinstance(nested, dict):
171
+ return cls.public_attachments(nested.get("attachments"))
172
+ payload = transaction.payload
173
+ if isinstance(payload, dict):
174
+ nested = payload.get("payload")
175
+ if isinstance(nested, dict):
176
+ return cls.public_attachments(nested.get("attachments"))
177
+ return []
178
+
179
+ @staticmethod
180
+ def with_attachments(
181
+ transaction: Transaction,
182
+ attachments: List[Dict[str, Any]],
183
+ ) -> Transaction:
184
+ """With the attachments."""
185
+ metadata = dict(transaction.metadata or {})
186
+ metadata["attachments"] = attachments
187
+ metadata["has_attachment"] = bool(attachments)
188
+ nested = metadata.get("message_payload")
189
+ if isinstance(nested, dict):
190
+ metadata["message_payload"] = {
191
+ **nested,
192
+ "attachments": attachments,
193
+ }
194
+ payload = transaction.payload
195
+ if isinstance(payload, dict):
196
+ payload = dict(payload)
197
+ inner = payload.get("payload")
198
+ if isinstance(inner, dict):
199
+ payload["payload"] = {
200
+ **inner,
201
+ "attachments": attachments,
202
+ }
203
+ return transaction.model_copy(update={"payload": payload, "metadata": metadata})
204
+
205
+ @staticmethod
206
+ def unseen(
207
+ transactions: List[Transaction],
208
+ seen_ids: set[str],
209
+ ) -> List[Transaction]:
210
+ fresh: List[Transaction] = []
211
+ """Unseen transactions."""
212
+ for transaction in transactions:
213
+ if not transaction.id or transaction.id in seen_ids:
214
+ continue
215
+ seen_ids.add(transaction.id)
216
+ fresh.append(transaction)
217
+ return fresh
218
+
219
+ @classmethod
220
+ def finalize_fetch(
221
+ cls,
222
+ transactions: List[Transaction],
223
+ config: ErgonPlatformChannelsConsumerConfig,
224
+ seen_ids: Optional[set[str]] = None,
225
+ ) -> List[Transaction]:
226
+ """Finalize the fetched transactions."""
227
+ transactions = config.effective_activity_filter().select(transactions)
228
+ if seen_ids is not None:
229
+ transactions = cls.unseen(transactions, seen_ids)
230
+ return transactions