unrealon 1.0.9__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. unrealon/__init__.py +23 -21
  2. unrealon-1.1.0.dist-info/METADATA +164 -0
  3. unrealon-1.1.0.dist-info/RECORD +82 -0
  4. {unrealon-1.0.9.dist-info → unrealon-1.1.0.dist-info}/WHEEL +1 -1
  5. unrealon-1.1.0.dist-info/entry_points.txt +9 -0
  6. {unrealon-1.0.9.dist-info → unrealon-1.1.0.dist-info/licenses}/LICENSE +1 -1
  7. unrealon_bridge/__init__.py +114 -0
  8. unrealon_bridge/cli.py +316 -0
  9. unrealon_bridge/client/__init__.py +93 -0
  10. unrealon_bridge/client/base.py +78 -0
  11. unrealon_bridge/client/commands.py +89 -0
  12. unrealon_bridge/client/connection.py +90 -0
  13. unrealon_bridge/client/events.py +65 -0
  14. unrealon_bridge/client/health.py +38 -0
  15. unrealon_bridge/client/html_parser.py +146 -0
  16. unrealon_bridge/client/logging.py +139 -0
  17. unrealon_bridge/client/proxy.py +70 -0
  18. unrealon_bridge/client/scheduler.py +450 -0
  19. unrealon_bridge/client/session.py +70 -0
  20. unrealon_bridge/configs/__init__.py +14 -0
  21. unrealon_bridge/configs/bridge_config.py +212 -0
  22. unrealon_bridge/configs/bridge_config.yaml +39 -0
  23. unrealon_bridge/models/__init__.py +138 -0
  24. unrealon_bridge/models/base.py +28 -0
  25. unrealon_bridge/models/command.py +41 -0
  26. unrealon_bridge/models/events.py +40 -0
  27. unrealon_bridge/models/html_parser.py +79 -0
  28. unrealon_bridge/models/logging.py +55 -0
  29. unrealon_bridge/models/parser.py +63 -0
  30. unrealon_bridge/models/proxy.py +41 -0
  31. unrealon_bridge/models/requests.py +95 -0
  32. unrealon_bridge/models/responses.py +88 -0
  33. unrealon_bridge/models/scheduler.py +592 -0
  34. unrealon_bridge/models/session.py +28 -0
  35. unrealon_bridge/server/__init__.py +91 -0
  36. unrealon_bridge/server/base.py +171 -0
  37. unrealon_bridge/server/handlers/__init__.py +23 -0
  38. unrealon_bridge/server/handlers/command.py +110 -0
  39. unrealon_bridge/server/handlers/html_parser.py +139 -0
  40. unrealon_bridge/server/handlers/logging.py +95 -0
  41. unrealon_bridge/server/handlers/parser.py +95 -0
  42. unrealon_bridge/server/handlers/proxy.py +75 -0
  43. unrealon_bridge/server/handlers/scheduler.py +545 -0
  44. unrealon_bridge/server/handlers/session.py +66 -0
  45. unrealon_browser/__init__.py +61 -18
  46. unrealon_browser/{src/cli → cli}/browser_cli.py +6 -13
  47. unrealon_browser/{src/cli → cli}/cookies_cli.py +5 -1
  48. unrealon_browser/{src/core → core}/browser_manager.py +2 -2
  49. unrealon_browser/{src/managers → managers}/captcha.py +1 -1
  50. unrealon_browser/{src/managers → managers}/cookies.py +1 -1
  51. unrealon_browser/managers/logger_bridge.py +231 -0
  52. unrealon_browser/{src/managers → managers}/profile.py +1 -1
  53. unrealon_driver/__init__.py +73 -19
  54. unrealon_driver/browser/__init__.py +8 -0
  55. unrealon_driver/browser/config.py +74 -0
  56. unrealon_driver/browser/manager.py +416 -0
  57. unrealon_driver/exceptions.py +28 -0
  58. unrealon_driver/parser/__init__.py +55 -0
  59. unrealon_driver/parser/cli_manager.py +141 -0
  60. unrealon_driver/parser/daemon_manager.py +227 -0
  61. unrealon_driver/parser/managers/__init__.py +46 -0
  62. unrealon_driver/parser/managers/browser.py +51 -0
  63. unrealon_driver/parser/managers/config.py +281 -0
  64. unrealon_driver/parser/managers/error.py +412 -0
  65. unrealon_driver/parser/managers/html.py +732 -0
  66. unrealon_driver/parser/managers/logging.py +609 -0
  67. unrealon_driver/parser/managers/result.py +321 -0
  68. unrealon_driver/parser/parser_manager.py +628 -0
  69. unrealon/sdk_config.py +0 -88
  70. unrealon-1.0.9.dist-info/METADATA +0 -810
  71. unrealon-1.0.9.dist-info/RECORD +0 -246
  72. unrealon_browser/pyproject.toml +0 -182
  73. unrealon_browser/src/__init__.py +0 -62
  74. unrealon_browser/src/managers/logger_bridge.py +0 -395
  75. unrealon_driver/README.md +0 -204
  76. unrealon_driver/pyproject.toml +0 -187
  77. unrealon_driver/src/__init__.py +0 -90
  78. unrealon_driver/src/cli/__init__.py +0 -10
  79. unrealon_driver/src/cli/main.py +0 -66
  80. unrealon_driver/src/cli/simple.py +0 -510
  81. unrealon_driver/src/config/__init__.py +0 -11
  82. unrealon_driver/src/config/auto_config.py +0 -478
  83. unrealon_driver/src/core/__init__.py +0 -18
  84. unrealon_driver/src/core/exceptions.py +0 -289
  85. unrealon_driver/src/core/parser.py +0 -638
  86. unrealon_driver/src/dto/__init__.py +0 -66
  87. unrealon_driver/src/dto/cli.py +0 -119
  88. unrealon_driver/src/dto/config.py +0 -18
  89. unrealon_driver/src/dto/events.py +0 -237
  90. unrealon_driver/src/dto/execution.py +0 -313
  91. unrealon_driver/src/dto/services.py +0 -311
  92. unrealon_driver/src/execution/__init__.py +0 -23
  93. unrealon_driver/src/execution/daemon_mode.py +0 -317
  94. unrealon_driver/src/execution/interactive_mode.py +0 -88
  95. unrealon_driver/src/execution/modes.py +0 -45
  96. unrealon_driver/src/execution/scheduled_mode.py +0 -209
  97. unrealon_driver/src/execution/test_mode.py +0 -250
  98. unrealon_driver/src/logging/__init__.py +0 -24
  99. unrealon_driver/src/logging/driver_logger.py +0 -512
  100. unrealon_driver/src/services/__init__.py +0 -24
  101. unrealon_driver/src/services/browser_service.py +0 -726
  102. unrealon_driver/src/services/llm/__init__.py +0 -15
  103. unrealon_driver/src/services/llm/browser_llm_service.py +0 -363
  104. unrealon_driver/src/services/llm/llm.py +0 -195
  105. unrealon_driver/src/services/logger_service.py +0 -232
  106. unrealon_driver/src/services/metrics_service.py +0 -185
  107. unrealon_driver/src/services/scheduler_service.py +0 -489
  108. unrealon_driver/src/services/websocket_service.py +0 -362
  109. unrealon_driver/src/utils/__init__.py +0 -16
  110. unrealon_driver/src/utils/service_factory.py +0 -317
  111. unrealon_driver/src/utils/time_formatter.py +0 -338
  112. unrealon_llm/README.md +0 -44
  113. unrealon_llm/__init__.py +0 -26
  114. unrealon_llm/pyproject.toml +0 -154
  115. unrealon_llm/src/__init__.py +0 -228
  116. unrealon_llm/src/cli/__init__.py +0 -0
  117. unrealon_llm/src/core/__init__.py +0 -11
  118. unrealon_llm/src/core/smart_client.py +0 -438
  119. unrealon_llm/src/dto/__init__.py +0 -155
  120. unrealon_llm/src/dto/models/__init__.py +0 -0
  121. unrealon_llm/src/dto/models/config.py +0 -343
  122. unrealon_llm/src/dto/models/core.py +0 -328
  123. unrealon_llm/src/dto/models/enums.py +0 -123
  124. unrealon_llm/src/dto/models/html_analysis.py +0 -345
  125. unrealon_llm/src/dto/models/statistics.py +0 -473
  126. unrealon_llm/src/dto/models/translation.py +0 -383
  127. unrealon_llm/src/dto/models/type_conversion.py +0 -462
  128. unrealon_llm/src/dto/schemas/__init__.py +0 -0
  129. unrealon_llm/src/exceptions.py +0 -392
  130. unrealon_llm/src/llm_config/__init__.py +0 -20
  131. unrealon_llm/src/llm_config/logging_config.py +0 -178
  132. unrealon_llm/src/llm_logging/__init__.py +0 -42
  133. unrealon_llm/src/llm_logging/llm_events.py +0 -107
  134. unrealon_llm/src/llm_logging/llm_logger.py +0 -466
  135. unrealon_llm/src/managers/__init__.py +0 -15
  136. unrealon_llm/src/managers/cache_manager.py +0 -67
  137. unrealon_llm/src/managers/cost_manager.py +0 -107
  138. unrealon_llm/src/managers/request_manager.py +0 -298
  139. unrealon_llm/src/modules/__init__.py +0 -0
  140. unrealon_llm/src/modules/html_processor/__init__.py +0 -25
  141. unrealon_llm/src/modules/html_processor/base_processor.py +0 -415
  142. unrealon_llm/src/modules/html_processor/details_processor.py +0 -85
  143. unrealon_llm/src/modules/html_processor/listing_processor.py +0 -91
  144. unrealon_llm/src/modules/html_processor/models/__init__.py +0 -20
  145. unrealon_llm/src/modules/html_processor/models/processing_models.py +0 -40
  146. unrealon_llm/src/modules/html_processor/models/universal_model.py +0 -56
  147. unrealon_llm/src/modules/html_processor/processor.py +0 -102
  148. unrealon_llm/src/modules/llm/__init__.py +0 -0
  149. unrealon_llm/src/modules/translator/__init__.py +0 -0
  150. unrealon_llm/src/provider.py +0 -116
  151. unrealon_llm/src/utils/__init__.py +0 -95
  152. unrealon_llm/src/utils/common.py +0 -64
  153. unrealon_llm/src/utils/data_extractor.py +0 -188
  154. unrealon_llm/src/utils/html_cleaner.py +0 -767
  155. unrealon_llm/src/utils/language_detector.py +0 -308
  156. unrealon_llm/src/utils/models_cache.py +0 -592
  157. unrealon_llm/src/utils/smart_counter.py +0 -229
  158. unrealon_llm/src/utils/token_counter.py +0 -189
  159. unrealon_sdk/README.md +0 -25
  160. unrealon_sdk/__init__.py +0 -30
  161. unrealon_sdk/pyproject.toml +0 -231
  162. unrealon_sdk/src/__init__.py +0 -150
  163. unrealon_sdk/src/cli/__init__.py +0 -12
  164. unrealon_sdk/src/cli/commands/__init__.py +0 -22
  165. unrealon_sdk/src/cli/commands/benchmark.py +0 -42
  166. unrealon_sdk/src/cli/commands/diagnostics.py +0 -573
  167. unrealon_sdk/src/cli/commands/health.py +0 -46
  168. unrealon_sdk/src/cli/commands/integration.py +0 -498
  169. unrealon_sdk/src/cli/commands/reports.py +0 -43
  170. unrealon_sdk/src/cli/commands/security.py +0 -36
  171. unrealon_sdk/src/cli/commands/server.py +0 -483
  172. unrealon_sdk/src/cli/commands/servers.py +0 -56
  173. unrealon_sdk/src/cli/commands/tests.py +0 -55
  174. unrealon_sdk/src/cli/main.py +0 -126
  175. unrealon_sdk/src/cli/utils/reporter.py +0 -519
  176. unrealon_sdk/src/clients/openapi.yaml +0 -3347
  177. unrealon_sdk/src/clients/python_http/__init__.py +0 -3
  178. unrealon_sdk/src/clients/python_http/api_config.py +0 -228
  179. unrealon_sdk/src/clients/python_http/models/BaseModel.py +0 -12
  180. unrealon_sdk/src/clients/python_http/models/BroadcastDeliveryStats.py +0 -33
  181. unrealon_sdk/src/clients/python_http/models/BroadcastMessage.py +0 -17
  182. unrealon_sdk/src/clients/python_http/models/BroadcastMessageRequest.py +0 -35
  183. unrealon_sdk/src/clients/python_http/models/BroadcastPriority.py +0 -10
  184. unrealon_sdk/src/clients/python_http/models/BroadcastResponse.py +0 -21
  185. unrealon_sdk/src/clients/python_http/models/BroadcastResultResponse.py +0 -33
  186. unrealon_sdk/src/clients/python_http/models/BroadcastTarget.py +0 -11
  187. unrealon_sdk/src/clients/python_http/models/ConnectionStats.py +0 -27
  188. unrealon_sdk/src/clients/python_http/models/ConnectionsResponse.py +0 -21
  189. unrealon_sdk/src/clients/python_http/models/DeveloperMessageResponse.py +0 -23
  190. unrealon_sdk/src/clients/python_http/models/ErrorResponse.py +0 -25
  191. unrealon_sdk/src/clients/python_http/models/HTTPValidationError.py +0 -16
  192. unrealon_sdk/src/clients/python_http/models/HealthResponse.py +0 -23
  193. unrealon_sdk/src/clients/python_http/models/HealthStatus.py +0 -33
  194. unrealon_sdk/src/clients/python_http/models/LogLevel.py +0 -10
  195. unrealon_sdk/src/clients/python_http/models/LoggingRequest.py +0 -27
  196. unrealon_sdk/src/clients/python_http/models/LoggingResponse.py +0 -23
  197. unrealon_sdk/src/clients/python_http/models/MaintenanceMode.py +0 -9
  198. unrealon_sdk/src/clients/python_http/models/MaintenanceModeRequest.py +0 -33
  199. unrealon_sdk/src/clients/python_http/models/MaintenanceStatusResponse.py +0 -39
  200. unrealon_sdk/src/clients/python_http/models/ParserCommandRequest.py +0 -25
  201. unrealon_sdk/src/clients/python_http/models/ParserMessageResponse.py +0 -21
  202. unrealon_sdk/src/clients/python_http/models/ParserRegistrationRequest.py +0 -28
  203. unrealon_sdk/src/clients/python_http/models/ParserRegistrationResponse.py +0 -25
  204. unrealon_sdk/src/clients/python_http/models/ParserType.py +0 -10
  205. unrealon_sdk/src/clients/python_http/models/ProxyBlockRequest.py +0 -19
  206. unrealon_sdk/src/clients/python_http/models/ProxyEndpointResponse.py +0 -20
  207. unrealon_sdk/src/clients/python_http/models/ProxyListResponse.py +0 -19
  208. unrealon_sdk/src/clients/python_http/models/ProxyProvider.py +0 -10
  209. unrealon_sdk/src/clients/python_http/models/ProxyPurchaseRequest.py +0 -25
  210. unrealon_sdk/src/clients/python_http/models/ProxyResponse.py +0 -47
  211. unrealon_sdk/src/clients/python_http/models/ProxyRotationRequest.py +0 -23
  212. unrealon_sdk/src/clients/python_http/models/ProxyStatus.py +0 -10
  213. unrealon_sdk/src/clients/python_http/models/ProxyUsageRequest.py +0 -19
  214. unrealon_sdk/src/clients/python_http/models/ProxyUsageStatsResponse.py +0 -26
  215. unrealon_sdk/src/clients/python_http/models/ServiceRegistrationDto.py +0 -23
  216. unrealon_sdk/src/clients/python_http/models/ServiceStatsResponse.py +0 -31
  217. unrealon_sdk/src/clients/python_http/models/SessionStartRequest.py +0 -23
  218. unrealon_sdk/src/clients/python_http/models/SuccessResponse.py +0 -25
  219. unrealon_sdk/src/clients/python_http/models/SystemNotificationResponse.py +0 -23
  220. unrealon_sdk/src/clients/python_http/models/ValidationError.py +0 -18
  221. unrealon_sdk/src/clients/python_http/models/ValidationErrorResponse.py +0 -21
  222. unrealon_sdk/src/clients/python_http/models/WebSocketMetrics.py +0 -21
  223. unrealon_sdk/src/clients/python_http/models/__init__.py +0 -44
  224. unrealon_sdk/src/clients/python_http/services/None_service.py +0 -35
  225. unrealon_sdk/src/clients/python_http/services/ParserManagement_service.py +0 -190
  226. unrealon_sdk/src/clients/python_http/services/ProxyManagement_service.py +0 -289
  227. unrealon_sdk/src/clients/python_http/services/SocketLogging_service.py +0 -187
  228. unrealon_sdk/src/clients/python_http/services/SystemHealth_service.py +0 -119
  229. unrealon_sdk/src/clients/python_http/services/WebSocketAPI_service.py +0 -198
  230. unrealon_sdk/src/clients/python_http/services/__init__.py +0 -0
  231. unrealon_sdk/src/clients/python_http/services/admin_service.py +0 -125
  232. unrealon_sdk/src/clients/python_http/services/async_None_service.py +0 -35
  233. unrealon_sdk/src/clients/python_http/services/async_ParserManagement_service.py +0 -190
  234. unrealon_sdk/src/clients/python_http/services/async_ProxyManagement_service.py +0 -289
  235. unrealon_sdk/src/clients/python_http/services/async_SocketLogging_service.py +0 -189
  236. unrealon_sdk/src/clients/python_http/services/async_SystemHealth_service.py +0 -123
  237. unrealon_sdk/src/clients/python_http/services/async_WebSocketAPI_service.py +0 -200
  238. unrealon_sdk/src/clients/python_http/services/async_admin_service.py +0 -125
  239. unrealon_sdk/src/clients/python_websocket/__init__.py +0 -28
  240. unrealon_sdk/src/clients/python_websocket/client.py +0 -490
  241. unrealon_sdk/src/clients/python_websocket/events.py +0 -732
  242. unrealon_sdk/src/clients/python_websocket/example.py +0 -136
  243. unrealon_sdk/src/clients/python_websocket/types.py +0 -871
  244. unrealon_sdk/src/core/__init__.py +0 -64
  245. unrealon_sdk/src/core/client.py +0 -556
  246. unrealon_sdk/src/core/config.py +0 -465
  247. unrealon_sdk/src/core/exceptions.py +0 -239
  248. unrealon_sdk/src/core/metadata.py +0 -191
  249. unrealon_sdk/src/core/models.py +0 -142
  250. unrealon_sdk/src/core/types.py +0 -68
  251. unrealon_sdk/src/dto/__init__.py +0 -268
  252. unrealon_sdk/src/dto/authentication.py +0 -108
  253. unrealon_sdk/src/dto/cache.py +0 -208
  254. unrealon_sdk/src/dto/common.py +0 -19
  255. unrealon_sdk/src/dto/concurrency.py +0 -393
  256. unrealon_sdk/src/dto/events.py +0 -108
  257. unrealon_sdk/src/dto/health.py +0 -339
  258. unrealon_sdk/src/dto/load_balancing.py +0 -336
  259. unrealon_sdk/src/dto/logging.py +0 -230
  260. unrealon_sdk/src/dto/performance.py +0 -165
  261. unrealon_sdk/src/dto/rate_limiting.py +0 -295
  262. unrealon_sdk/src/dto/resource_pooling.py +0 -128
  263. unrealon_sdk/src/dto/structured_logging.py +0 -112
  264. unrealon_sdk/src/dto/task_scheduling.py +0 -121
  265. unrealon_sdk/src/dto/websocket.py +0 -55
  266. unrealon_sdk/src/enterprise/__init__.py +0 -59
  267. unrealon_sdk/src/enterprise/authentication.py +0 -401
  268. unrealon_sdk/src/enterprise/cache_manager.py +0 -578
  269. unrealon_sdk/src/enterprise/error_recovery.py +0 -494
  270. unrealon_sdk/src/enterprise/event_system.py +0 -549
  271. unrealon_sdk/src/enterprise/health_monitor.py +0 -747
  272. unrealon_sdk/src/enterprise/load_balancer.py +0 -964
  273. unrealon_sdk/src/enterprise/logging/__init__.py +0 -68
  274. unrealon_sdk/src/enterprise/logging/cleanup.py +0 -156
  275. unrealon_sdk/src/enterprise/logging/development.py +0 -744
  276. unrealon_sdk/src/enterprise/logging/service.py +0 -410
  277. unrealon_sdk/src/enterprise/multithreading_manager.py +0 -853
  278. unrealon_sdk/src/enterprise/performance_monitor.py +0 -539
  279. unrealon_sdk/src/enterprise/proxy_manager.py +0 -696
  280. unrealon_sdk/src/enterprise/rate_limiter.py +0 -652
  281. unrealon_sdk/src/enterprise/resource_pool.py +0 -763
  282. unrealon_sdk/src/enterprise/task_scheduler.py +0 -709
  283. unrealon_sdk/src/internal/__init__.py +0 -10
  284. unrealon_sdk/src/internal/command_router.py +0 -497
  285. unrealon_sdk/src/internal/connection_manager.py +0 -397
  286. unrealon_sdk/src/internal/http_client.py +0 -446
  287. unrealon_sdk/src/internal/websocket_client.py +0 -420
  288. unrealon_sdk/src/provider.py +0 -471
  289. unrealon_sdk/src/utils.py +0 -234
  290. /unrealon_browser/{src/cli → cli}/__init__.py +0 -0
  291. /unrealon_browser/{src/cli → cli}/interactive_mode.py +0 -0
  292. /unrealon_browser/{src/cli → cli}/main.py +0 -0
  293. /unrealon_browser/{src/core → core}/__init__.py +0 -0
  294. /unrealon_browser/{src/dto → dto}/__init__.py +0 -0
  295. /unrealon_browser/{src/dto → dto}/models/config.py +0 -0
  296. /unrealon_browser/{src/dto → dto}/models/core.py +0 -0
  297. /unrealon_browser/{src/dto → dto}/models/dataclasses.py +0 -0
  298. /unrealon_browser/{src/dto → dto}/models/detection.py +0 -0
  299. /unrealon_browser/{src/dto → dto}/models/enums.py +0 -0
  300. /unrealon_browser/{src/dto → dto}/models/statistics.py +0 -0
  301. /unrealon_browser/{src/managers → managers}/__init__.py +0 -0
  302. /unrealon_browser/{src/managers → managers}/stealth.py +0 -0
@@ -1,64 +0,0 @@
1
- """
2
- Core SDK components for UnrealOn SDK v1.0
3
-
4
- This module contains the essential SDK functionality:
5
- - Types and data structures
6
- - Exception hierarchy
7
- - Configuration management
8
- - Core models
9
- """
10
-
11
- from .types import ConnectionState
12
- from .models import ConnectionHealthStatus, ComponentStatus
13
- from .metadata import (
14
- SDKMetadata,
15
- RegistrationMetadata,
16
- CommandExecutionMetadata,
17
- LoggingContextMetadata,
18
- EnvironmentMetadata,
19
- ProxyOperationMetadata,
20
- )
21
- from .exceptions import (
22
- UnrealOnError,
23
- ConnectionError,
24
- AuthenticationError,
25
- ConfigurationError,
26
- CommandError,
27
- ProxyError,
28
- TimeoutError,
29
- ValidationError,
30
- RegistrationError,
31
- WebSocketError,
32
- MonitoringError,
33
- LoggingError,
34
- RateLimitError,
35
- )
36
-
37
- __all__ = [
38
- # Types
39
- "ConnectionState",
40
- # Models
41
- "ConnectionHealthStatus",
42
- "ComponentStatus",
43
- # Metadata
44
- "SDKMetadata",
45
- "RegistrationMetadata",
46
- "CommandExecutionMetadata",
47
- "LoggingContextMetadata",
48
- "EnvironmentMetadata",
49
- "ProxyOperationMetadata",
50
- # Exceptions
51
- "UnrealOnError",
52
- "ConnectionError",
53
- "AuthenticationError",
54
- "ConfigurationError",
55
- "CommandError",
56
- "ProxyError",
57
- "TimeoutError",
58
- "ValidationError",
59
- "RegistrationError",
60
- "WebSocketError",
61
- "MonitoringError",
62
- "LoggingError",
63
- "RateLimitError",
64
- ]
@@ -1,556 +0,0 @@
1
- """
2
- Main AdapterClient for UnrealOn SDK v1.0
3
-
4
- Provides the primary interface for parser integration with:
5
- - Zero-configuration setup
6
- - Type-safe operations
7
- - Real-time communication
8
- - Enterprise features out of the box
9
- """
10
-
11
- import asyncio
12
- import logging
13
- import os
14
- import subprocess
15
- import uuid
16
- from datetime import datetime
17
- from logging.handlers import RotatingFileHandler
18
- from typing import Dict, Any, Optional, Callable, List, Awaitable, Union
19
-
20
- from .config import AdapterConfig
21
- from .types import ConnectionState
22
- from .exceptions import (
23
- UnrealOnError,
24
- ConnectionError,
25
- ConfigurationError,
26
- CommandError,
27
- RegistrationError,
28
- )
29
-
30
- # Use auto-generated models only!
31
- from unrealon_sdk.src.clients.python_websocket.types import ParserCommandEvent, ServiceType
32
- from unrealon_sdk.src.clients.python_http.models import (
33
- ParserRegistrationRequest,
34
- ParserRegistrationResponse,
35
- ServiceRegistrationDto,
36
- LogLevel,
37
- SuccessResponse,
38
- ErrorResponse,
39
- LoggingRequest,
40
- )
41
-
42
- # Internal components that we'll create
43
- from unrealon_sdk.src.internal.connection_manager import ConnectionManager
44
- from unrealon_sdk.src.internal.command_router import CommandRouter
45
-
46
- from unrealon_sdk.src.utils import generate_correlation_id, format_duration
47
-
48
- # Development logging
49
- from unrealon_sdk.src.enterprise.logging.development import (
50
- initialize_development_logger,
51
- get_development_logger,
52
- SDKEventType,
53
- SDKContext,
54
- SDKSeverity,
55
- track_development_operation,
56
- )
57
-
58
- # Metadata models
59
- from unrealon_sdk.src.core.metadata import LoggingContextMetadata
60
-
61
-
62
- class AdapterClient:
63
- """
64
- Main client for UnrealOn Adapter integration.
65
-
66
- Provides enterprise-grade parsing orchestration with:
67
- - Zero-configuration setup
68
- - Type-safe operations
69
- - Real-time communication
70
- - Production monitoring
71
-
72
- Example:
73
- ```python
74
- from unrealon_sdk import AdapterClient, AdapterConfig
75
-
76
- config = AdapterConfig(
77
- api_key="up_dev_your_key",
78
- parser_id="my_parser",
79
- parser_name="My Parser"
80
- )
81
- adapter = AdapterClient(config)
82
-
83
- @adapter.on_command("parse_listing")
84
- async def handle_parsing(command: ParserCommandEvent) -> SuccessResponse:
85
- # Use type-safe Pydantic models
86
- result = MyListingData(
87
- title="Extracted data",
88
- price=15000000
89
- )
90
- return SuccessResponse(
91
- success=True,
92
- data=result.model_dump()
93
- )
94
-
95
- await adapter.start()
96
- ```
97
- """
98
-
99
- def __init__(self, config: AdapterConfig):
100
- """
101
- Initialize the AdapterClient.
102
-
103
- Args:
104
- config: Configuration for the adapter client
105
- """
106
- self.config = config
107
- self.parser_id = config.parser_id
108
- self.logger = self._setup_logging()
109
-
110
- # Internal components
111
- self._connection_manager: Optional[ConnectionManager] = None
112
- self._command_router = CommandRouter()
113
- self._command_handlers: Dict[
114
- str, Callable[[ParserCommandEvent], Awaitable[Union[SuccessResponse, ErrorResponse]]]
115
- ] = {}
116
- self._services: List[ServiceRegistrationDto] = []
117
-
118
- # State tracking
119
- self._connection_state = ConnectionState()
120
- self._running = False
121
- self._startup_complete = False
122
-
123
- self.logger.info(f"AdapterClient initialized for parser {self.parser_id}")
124
-
125
- def on_command(self, command_type: str) -> Callable[
126
- [Callable[[ParserCommandEvent], Awaitable[Union[SuccessResponse, ErrorResponse]]]],
127
- Callable[[ParserCommandEvent], Awaitable[Union[SuccessResponse, ErrorResponse]]],
128
- ]:
129
- """
130
- Decorator for registering command handlers.
131
-
132
- Args:
133
- command_type: Type of command to handle
134
-
135
- Returns:
136
- Decorator function
137
-
138
- Example:
139
- @adapter.on_command("parse_listing")
140
- async def handle_parsing(command: ParserCommandEvent) -> SuccessResponse:
141
- # Use type-safe parsing with Pydantic models
142
- result = ExtractedData(extracted="data")
143
- return SuccessResponse(success=True, data=result.model_dump())
144
- """
145
-
146
- def decorator(
147
- func: Callable[[ParserCommandEvent], Awaitable[Union[SuccessResponse, ErrorResponse]]]
148
- ) -> Callable:
149
- self._command_handlers[command_type] = func
150
- self._command_router.register_handler(command_type, func)
151
- self.logger.info(f"Registered handler for command type: {command_type}")
152
- return func
153
-
154
- return decorator
155
-
156
- def _setup_logging(self) -> logging.Logger:
157
- """Setup logging for the client with automatic log cleanup."""
158
- # Use standard logger - cleanup handled at module initialization
159
- logger = logging.getLogger(f"unrealon_sdk.{self.parser_id}")
160
-
161
- # Set log level based on configuration
162
- log_level_map = {
163
- LogLevel.DEBUG: logging.DEBUG,
164
- LogLevel.INFO: logging.INFO,
165
- LogLevel.WARNING: logging.WARNING,
166
- LogLevel.ERROR: logging.ERROR,
167
- LogLevel.CRITICAL: logging.CRITICAL,
168
- }
169
- log_level = LogLevel.INFO
170
- if self.config.logging_config:
171
- log_level = self.config.logging_config.log_level
172
- logger.setLevel(log_level_map.get(log_level, logging.INFO))
173
-
174
- # Add handlers if not exists
175
- if not logger.handlers:
176
- # Console handler
177
- console_handler = logging.StreamHandler()
178
- formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
179
- console_handler.setFormatter(formatter)
180
- logger.addHandler(console_handler)
181
-
182
- # File handler - create logs directory if needed
183
- if self.config.logging_config and self.config.logging_config.log_file_path:
184
- log_path = self.config.logging_config.log_file_path
185
- else:
186
- # Create log path at SDK root level (one level up from unrealon_sdk/)
187
- sdk_root = os.path.dirname(
188
- os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
189
- )
190
- log_path = os.path.join(sdk_root, "logs", "unrealon_sdk.log")
191
-
192
- os.makedirs(os.path.dirname(log_path), exist_ok=True)
193
-
194
- file_handler = RotatingFileHandler(
195
- log_path, maxBytes=50 * 1024 * 1024, backupCount=10 # 50MB
196
- )
197
- file_handler.setFormatter(formatter)
198
- logger.addHandler(file_handler)
199
-
200
- logger.info(f"SDK logging configured - Console: ✅ File: {log_path}")
201
-
202
- return logger
203
-
204
- async def register_services(self, services: List[ServiceRegistrationDto]) -> None:
205
- """
206
- Register services that this parser provides.
207
-
208
- Args:
209
- services: List of services to register
210
- """
211
- self._services = services
212
- self.logger.info(f"Registered {len(services)} services")
213
-
214
- async def connect(self) -> None:
215
- """
216
- Establish connection to the UnrealOn Adapter.
217
-
218
- Raises:
219
- ConnectionError: If connection fails
220
- ConfigurationError: If configuration is invalid
221
- """
222
- try:
223
- self.logger.info("Connecting to UnrealOn Adapter...")
224
-
225
- # Initialize connection manager
226
- self._connection_manager = ConnectionManager(
227
- config=self.config, parser_id=self.parser_id, logger=self.logger
228
- )
229
-
230
- # Connect to adapter
231
- await self._connection_manager.connect()
232
-
233
- # Register parser and services
234
- await self._register_parser()
235
-
236
- # Setup command handling
237
- self._connection_manager.set_command_handler(self._handle_command)
238
-
239
- self._connection_state.mark_connected(self._connection_manager.get_session_id())
240
-
241
- self.logger.info("Successfully connected to UnrealOn Adapter")
242
-
243
- except Exception as e:
244
- self._connection_state.mark_disconnected(str(e))
245
- self.logger.error(f"Failed to connect to adapter: {e}")
246
- raise ConnectionError(f"Connection failed: {e}")
247
-
248
- def _ensure_default_service(self) -> None:
249
- """Ensure there's at least one service registered based on command handlers."""
250
- if not self._services:
251
- # Extract registered commands from handlers
252
- registered_commands = list(self._command_handlers.keys())
253
-
254
- # Create default service based on registered commands using proper Pydantic v2 model
255
- default_service = ServiceRegistrationDto(
256
- service_id=f"{self.parser_id}_service",
257
- service_name=f"{self.config.parser_name} Service",
258
- service_type=ServiceType.SCRAPER.value, # Use valid ServiceType
259
- capabilities={
260
- "commands": registered_commands if registered_commands else ["status"],
261
- "features": self._get_enabled_features(),
262
- },
263
- config={
264
- "timeout": self.config.request_timeout_ms,
265
- "max_retries": self.config.max_retries,
266
- "environment": self.config.environment,
267
- },
268
- )
269
-
270
- self._services = [default_service]
271
- self.logger.info(f"Created default service with commands: {registered_commands}")
272
-
273
- def _get_enabled_features(self) -> List[str]:
274
- """Get list of enabled features for service capabilities."""
275
- features = ["monitoring", "logging"]
276
- if self.config.enable_proxy_rotation:
277
- features.append("proxy_rotation")
278
- if self.config.enable_error_recovery:
279
- features.append("error_recovery")
280
- return features
281
-
282
- async def _register_parser(self) -> None:
283
- """Register this parser with the adapter using auto-generated client."""
284
- try:
285
- # Ensure we have at least one service before registration
286
- self._ensure_default_service()
287
-
288
- # Create typed registration request using auto-generated model
289
- registration_request = ParserRegistrationRequest(
290
- parser_id=self.parser_id,
291
- parser_name=self.config.parser_name,
292
- parser_type=self.config.parser_type,
293
- api_key=self.config.api_key,
294
- services=self._services,
295
- metadata={
296
- "sdk_version": "1.0.0",
297
- "environment": self.config.environment,
298
- "features": {
299
- "proxy_rotation": self.config.enable_proxy_rotation,
300
- "monitoring": self.config.enable_monitoring,
301
- "logging": self.config.enable_logging,
302
- },
303
- },
304
- )
305
-
306
- if self._connection_manager is None:
307
- raise ConfigurationError("Connection manager not initialized")
308
-
309
- # Use auto-generated client for registration
310
- response = await self._connection_manager.register_parser(registration_request)
311
-
312
- if not response.success:
313
- raise RegistrationError(
314
- f"Parser registration failed: {response.error or 'Unknown error'}"
315
- )
316
-
317
- self.logger.info(
318
- f"Parser registered successfully. Services: {response.registered_services or []}"
319
- )
320
-
321
- except Exception as e:
322
- self.logger.error(f"Parser registration failed: {e}")
323
- raise
324
-
325
- async def _handle_command(self, command: ParserCommandEvent) -> None:
326
- """
327
- Handle incoming commands from the adapter using command router.
328
-
329
- Args:
330
- command: Command event to handle
331
- """
332
- start_time = datetime.now()
333
- correlation_id = command.correlation_id or str(uuid.uuid4())
334
-
335
- self.logger.info(
336
- f"Received command {command.command_id} of type {command.command_type}",
337
- extra={"correlation_id": correlation_id},
338
- )
339
-
340
- try:
341
- # Use command router to handle the command
342
- response = await self._command_router.route_command(command)
343
-
344
- # Send response back to adapter
345
- await self._send_response(response)
346
-
347
- execution_time = (datetime.now() - start_time).total_seconds() * 1000
348
- self.logger.info(
349
- f"Command {command.command_id} completed in {execution_time:.2f}ms",
350
- extra={"correlation_id": correlation_id},
351
- )
352
-
353
- except Exception as e:
354
- execution_time = (datetime.now() - start_time).total_seconds() * 1000
355
-
356
- # Send error response
357
- response = ErrorResponse(
358
- success=False, message=str(e), error_code=getattr(e, "error_code", "UNKNOWN_ERROR")
359
- )
360
-
361
- await self._send_response(response)
362
-
363
- self.logger.error(
364
- f"Command {command.command_id} failed after {execution_time:.2f}ms: {e}",
365
- extra={"correlation_id": correlation_id},
366
- )
367
-
368
- async def _send_response(self, response: Union[SuccessResponse, ErrorResponse]) -> None:
369
- """Send command response back to adapter."""
370
- if self._connection_manager is None:
371
- raise ConnectionError("Not connected to adapter")
372
-
373
- await self._connection_manager.send_response(response)
374
-
375
- def _kill_existing_parser_processes(self) -> None:
376
- """Kill existing parser processes to avoid port conflicts."""
377
- try:
378
- # Simple approach: kill processes by script name + parser_id in process name
379
- script_name = f"{self.config.parser_id}.py"
380
- current_pid = os.getpid()
381
-
382
- # Find processes running the same parser script
383
- result = subprocess.run(
384
- ["pgrep", "-f", script_name], capture_output=True, text=True, timeout=3
385
- )
386
-
387
- if result.returncode == 0 and result.stdout.strip():
388
- pids = [int(p.strip()) for p in result.stdout.strip().split("\n") if p.strip()]
389
- for pid in pids:
390
- if pid != current_pid: # Don't kill ourselves
391
- try:
392
- subprocess.run(["kill", "-TERM", str(pid)], timeout=1)
393
- self.logger.info(f"🔄 Killed existing parser: PID {pid}")
394
- except:
395
- pass # Ignore errors, process might be already dead
396
-
397
- except Exception:
398
- # Ignore all errors - this is just cleanup, not critical
399
- pass
400
-
401
- async def start(self) -> None:
402
- """
403
- Start the adapter client and begin processing commands.
404
-
405
- This method will:
406
- 0. Kill existing parser processes to avoid conflicts
407
- 1. Connect to the adapter
408
- 2. Register the parser and services
409
- 3. Start listening for commands
410
- """
411
- if self._running:
412
- self.logger.warning("AdapterClient is already running")
413
- return
414
-
415
- try:
416
- # Kill existing parser processes first
417
- self._kill_existing_parser_processes()
418
-
419
- await self.connect()
420
- self._running = True
421
- self._startup_complete = True
422
-
423
- self.logger.info("AdapterClient started successfully")
424
-
425
- except Exception as e:
426
- self.logger.error(f"Failed to start AdapterClient: {e}")
427
- raise
428
-
429
- async def stop(self) -> None:
430
- """
431
- Stop the adapter client and disconnect from the adapter.
432
- """
433
- if not self._running:
434
- self.logger.warning("AdapterClient is not running")
435
- return
436
-
437
- try:
438
- self._running = False
439
-
440
- # Stop command router
441
- await self._command_router.shutdown()
442
-
443
- if self._connection_manager:
444
- await self._connection_manager.disconnect()
445
-
446
- self._connection_state.mark_disconnected()
447
- self.logger.info("AdapterClient stopped successfully")
448
-
449
- except Exception as e:
450
- self.logger.error(f"Error stopping AdapterClient: {e}")
451
- raise
452
-
453
- async def run_forever(self) -> None:
454
- """
455
- Keep the adapter client running indefinitely.
456
-
457
- This method will block until the client is stopped.
458
- """
459
- if not self._startup_complete:
460
- await self.start()
461
-
462
- try:
463
- self.logger.info("AdapterClient running indefinitely. Press Ctrl+C to stop.")
464
-
465
- while self._running:
466
- await asyncio.sleep(1)
467
-
468
- # Health check and reconnection logic
469
- if self._connection_manager:
470
- is_connected = self._connection_manager.is_connected()
471
- if not is_connected:
472
- # Debug: Check detailed connection status
473
- websocket_client = getattr(self._connection_manager, '_websocket_client', None)
474
- if websocket_client:
475
- connection_established = getattr(websocket_client, '_connection_established', False)
476
- client_connected = getattr(websocket_client._client, 'connected', False) if hasattr(websocket_client, '_client') else False
477
- manager_connected = getattr(self._connection_manager, '_connected', False)
478
-
479
- self.logger.warning(f"🔍 Connection check details:")
480
- self.logger.warning(f" manager._connected: {manager_connected}")
481
- self.logger.warning(f" websocket._connection_established: {connection_established}")
482
- self.logger.warning(f" socketio_client.connected: {client_connected}")
483
-
484
- self.logger.warning("Connection lost, attempting to reconnect...")
485
- try:
486
- await self._connection_manager.reconnect()
487
- self.logger.info("Reconnected successfully")
488
- except Exception as e:
489
- self.logger.error(f"Reconnection failed: {e}")
490
- await asyncio.sleep(5) # Wait before next attempt
491
-
492
- except KeyboardInterrupt:
493
- self.logger.info("Received interrupt signal, shutting down...")
494
-
495
- finally:
496
- await self.stop()
497
-
498
- async def send_log(
499
- self, level: LogLevel, message: str, context: Optional[LoggingContextMetadata] = None
500
- ) -> None:
501
- """
502
- Send a log entry to the adapter.
503
-
504
- Args:
505
- level: Log level
506
- message: Log message
507
- context: Additional context
508
- """
509
- if self._connection_manager and self.config.enable_logging:
510
- await self._connection_manager.send_log(level, message, context or {})
511
-
512
- async def log_info(
513
- self, message: str, context: Optional[LoggingContextMetadata] = None
514
- ) -> None:
515
- """Send info level log."""
516
- await self.send_log(LogLevel.INFO, message, context)
517
-
518
- async def log_warning(
519
- self, message: str, context: Optional[LoggingContextMetadata] = None
520
- ) -> None:
521
- """Send warning level log."""
522
- await self.send_log(LogLevel.WARNING, message, context)
523
-
524
- async def log_error(
525
- self, message: str, context: Optional[LoggingContextMetadata] = None
526
- ) -> None:
527
- """Send error level log."""
528
- await self.send_log(LogLevel.ERROR, message, context)
529
-
530
- def get_connection_status(self) -> ConnectionState:
531
- """Get current connection status."""
532
- return self._connection_state
533
-
534
- def is_connected(self) -> bool:
535
- """Check if connected to adapter."""
536
- return self._connection_state.connected and (
537
- self._connection_manager is not None and self._connection_manager.is_connected()
538
- )
539
-
540
- def get_registered_commands(self) -> List[str]:
541
- """Get list of registered command types."""
542
- return list(self._command_handlers.keys())
543
-
544
- def get_registered_services(self) -> List[ServiceRegistrationDto]:
545
- """Get list of registered services."""
546
- return self._services.copy()
547
-
548
- # Context manager support
549
- async def __aenter__(self) -> "AdapterClient":
550
- """Async context manager entry."""
551
- await self.start()
552
- return self
553
-
554
- async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
555
- """Async context manager exit."""
556
- await self.stop()