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,420 +0,0 @@
1
- """
2
- WebSocket client wrapper for UnrealOn SDK v1.0
3
-
4
- Wraps the auto-generated WebSocket client with SDK-specific functionality:
5
- - Type-safe event handling
6
- - Automatic reconnection with exponential backoff
7
- - Command routing integration
8
- - Health monitoring
9
- - Error recovery
10
- """
11
-
12
- import asyncio
13
- import logging
14
- from typing import Optional, Callable, Dict, Any, Union, Awaitable
15
- from datetime import datetime
16
-
17
- from pydantic import BaseModel, Field, ConfigDict
18
-
19
- from unrealon_sdk.src.core.config import AdapterConfig
20
- from unrealon_sdk.src.core.exceptions import WebSocketError, ConnectionError
21
- from unrealon_sdk.src.clients.python_http.models import ConnectionStats
22
- from unrealon_sdk.src.clients.python_websocket.client import WebSocketClient, WebSocketConfig
23
- from unrealon_sdk.src.clients.python_websocket.events import SocketEvent
24
- from unrealon_sdk.src.clients.python_websocket import WebSocketRoutes
25
- from unrealon_sdk.src.clients.python_websocket.types import (
26
- ParserCommandEvent,
27
- ParserWebSocketRegistrationRequest,
28
- )
29
- from unrealon_sdk.src.clients.python_http.models import SuccessResponse, ErrorResponse
30
-
31
- # Import from centralized logging service
32
- from unrealon_sdk.src.enterprise.logging.service import LoggingRequest
33
-
34
- # Use DTO models for type-safe data structures
35
- from unrealon_sdk.src.dto.websocket import WebSocketConnectionState, WebSocketStateInfo
36
- from unrealon_sdk.src.utils import generate_correlation_id
37
-
38
-
39
- # WebSocketConnectionState moved to unrealon_sdk.dto.websocket
40
-
41
-
42
- class WebSocketClientWrapper:
43
- """
44
- Wrapper for auto-generated WebSocket client.
45
-
46
- Provides SDK-specific functionality while using the generated client
47
- for actual WebSocket communication.
48
-
49
- Features:
50
- - Automatic reconnection with exponential backoff
51
- - Type-safe event handling with Pydantic validation
52
- - Command routing integration
53
- - Health monitoring and diagnostics
54
- - Error recovery and circuit breaker pattern
55
- """
56
-
57
- def __init__(self, config: AdapterConfig, parser_id: str, logger: logging.Logger):
58
- """
59
- Initialize WebSocket client wrapper.
60
-
61
- Args:
62
- config: Adapter configuration
63
- parser_id: Unique parser identifier
64
- logger: Logger instance
65
- """
66
- self.config = config
67
- self.parser_id = parser_id
68
- self.logger = logger
69
-
70
- # Create WebSocket configuration from adapter config
71
- # Build parser-specific WebSocket URL using generated routes
72
- parser_ws_url = WebSocketRoutes.get_parser_url(config.server_url, parser_id)
73
-
74
- ws_config = WebSocketConfig(
75
- url=parser_ws_url, # Use parser-specific endpoint from generated routes
76
- auto_connect=False, # We handle connection manually
77
- reconnection_attempts=5,
78
- reconnection_delay=1,
79
- timeout=config.request_timeout_ms / 1000, # Convert to seconds
80
- auth={"api_key": config.api_key, "parser_id": parser_id},
81
- headers={"User-Agent": f"UnrealOn-SDK/1.0 Parser/{parser_id}"},
82
- )
83
-
84
- # Initialize the generated WebSocket client
85
- self._client = WebSocketClient(ws_config)
86
-
87
- # Event handlers (can be sync or async)
88
- self._command_handler: Optional[
89
- Callable[[ParserCommandEvent], Union[None, Awaitable[None]]]
90
- ] = None
91
- self._connection_handler: Optional[Callable[[str, Any], Union[None, Awaitable[None]]]] = (
92
- None
93
- )
94
-
95
- # State tracking
96
- self._reconnect_count = 0
97
- self._last_ping: Optional[datetime] = None
98
- self._connection_established = False
99
-
100
- # Setup internal event handlers
101
- self._setup_event_handlers()
102
-
103
- self.logger.debug(f"WebSocketClientWrapper initialized for parser {parser_id}")
104
-
105
- async def _call_handler(self, handler: Optional[Callable[..., Any]], *args: Any) -> None:
106
- """
107
- Safely call handler, supporting both sync and async handlers.
108
-
109
- Args:
110
- handler: Handler function (sync or async)
111
- *args: Arguments to pass to handler
112
- """
113
- if handler is None:
114
- return
115
-
116
- try:
117
- result = handler(*args)
118
- if asyncio.iscoroutine(result):
119
- await result
120
- except Exception as e:
121
- self.logger.error(f"Error in handler: {e}")
122
-
123
- def _setup_event_handlers(self) -> None:
124
- """Setup event handlers for the generated WebSocket client."""
125
-
126
- @self._client.on(SocketEvent.CONNECT) # type: ignore[misc]
127
- async def on_connect(data: Any) -> None:
128
- """Handle WebSocket connection established."""
129
- self._connection_established = True
130
- self._reconnect_count = 0
131
- self._last_ping = datetime.utcnow()
132
-
133
- self.logger.info("WebSocket connection established")
134
-
135
- # Small delay to ensure Socket.IO client is fully ready to emit
136
- await asyncio.sleep(0.1)
137
-
138
- # Send parser registration to server using auto-generated Pydantic v2 model
139
- try:
140
- developer_id = "dev_integration_test" # Extract from API key if needed
141
-
142
- registration_request = ParserWebSocketRegistrationRequest(
143
- parser_id=self.parser_id, developer_id=developer_id
144
- )
145
-
146
- # Use the underlying Socket.IO client directly for proper event emission
147
- self.logger.debug(f"🔍 Emitting parser_register: event={SocketEvent.PARSER_REGISTER.value}, data={registration_request.model_dump()}")
148
- await self._client.sio.emit(
149
- SocketEvent.PARSER_REGISTER.value,
150
- registration_request.model_dump(),
151
- namespace='/'
152
- )
153
- self.logger.debug(f"🔍 Emit completed successfully")
154
- self.logger.info(f"🚀 Sent parser registration: {self.parser_id}")
155
- except Exception as e:
156
- self.logger.error(f"Failed to send parser registration: {e}")
157
-
158
- await self._call_handler(
159
- self._connection_handler, "connected", {"timestamp": datetime.utcnow().isoformat()}
160
- )
161
-
162
- @self._client.on(SocketEvent.DISCONNECT) # type: ignore[misc]
163
- async def on_disconnect(data: Any) -> None:
164
- """Handle WebSocket disconnection."""
165
- self._connection_established = False
166
-
167
- self.logger.warning("WebSocket connection lost")
168
-
169
- await self._call_handler(
170
- self._connection_handler, "disconnected", {"reason": data or "unknown"}
171
- )
172
-
173
- @self._client.on(SocketEvent.PARSER_COMMAND) # type: ignore[misc]
174
- async def on_parser_command(data: Any) -> None:
175
- """Handle incoming parser command."""
176
- try:
177
- # Validate and parse command using Pydantic
178
- command_event = ParserCommandEvent.model_validate(data)
179
-
180
- self.logger.debug(f"Received command: {command_event.command_id}")
181
-
182
- await self._call_handler(self._command_handler, command_event)
183
-
184
- if self._command_handler is None:
185
- self.logger.warning(
186
- f"No command handler registered for command {command_event.command_id}"
187
- )
188
-
189
- except Exception as e:
190
- self.logger.error(f"Error processing command: {e}")
191
- await self._call_handler(
192
- self._connection_handler,
193
- "error",
194
- {"error": str(e), "context": "command_processing"},
195
- )
196
-
197
- @self._client.on(SocketEvent.PING) # type: ignore[misc]
198
- async def on_ping(data: Any) -> None:
199
- """Handle ping from server."""
200
- self._last_ping = datetime.utcnow()
201
-
202
- # Respond with pong
203
- await self._client.emit(
204
- SocketEvent.PONG,
205
- {"timestamp": self._last_ping.isoformat(), "parser_id": self.parser_id},
206
- )
207
-
208
- @self._client.on(SocketEvent.ERROR) # type: ignore[misc]
209
- async def on_error(data: Any) -> None:
210
- """Handle WebSocket errors."""
211
- error_msg = (
212
- data.get("message", "Unknown WebSocket error")
213
- if isinstance(data, dict)
214
- else str(data)
215
- )
216
-
217
- self.logger.error(f"WebSocket error: {error_msg}")
218
-
219
- await self._call_handler(
220
- self._connection_handler, "error", {"error": error_msg, "context": "websocket"}
221
- )
222
-
223
- async def connect(self) -> None:
224
- """
225
- Connect to WebSocket server.
226
-
227
- Raises:
228
- WebSocketError: If connection fails
229
- """
230
- try:
231
- self.logger.info(f"Connecting to WebSocket server: {self.config.server_url}")
232
-
233
- success = await self._client.connect()
234
- if not success:
235
- raise WebSocketError("Failed to establish WebSocket connection")
236
-
237
- # Wait for connection to be fully established
238
- timeout = self.config.request_timeout_ms / 1000
239
- start_time = datetime.utcnow()
240
-
241
- while not self._connection_established:
242
- if (datetime.utcnow() - start_time).total_seconds() > timeout:
243
- raise WebSocketError("Connection timeout")
244
- await asyncio.sleep(0.1)
245
-
246
- self.logger.info("WebSocket connection established successfully")
247
-
248
- except Exception as e:
249
- self.logger.error(f"WebSocket connection failed: {e}")
250
- raise WebSocketError(f"Connection failed: {e}")
251
-
252
- async def disconnect(self) -> None:
253
- """Disconnect from WebSocket server."""
254
- try:
255
- self.logger.info("Disconnecting from WebSocket server")
256
-
257
- await self._client.disconnect()
258
- self._connection_established = False
259
-
260
- self.logger.info("WebSocket disconnected successfully")
261
-
262
- except Exception as e:
263
- self.logger.error(f"Error during WebSocket disconnect: {e}")
264
- raise WebSocketError(f"Disconnect failed: {e}")
265
-
266
- async def reconnect(self) -> None:
267
- """
268
- Reconnect to WebSocket server with exponential backoff.
269
-
270
- Raises:
271
- WebSocketError: If reconnection fails
272
- """
273
- self._reconnect_count += 1
274
-
275
- # Calculate backoff delay (exponential with jitter)
276
- base_delay = min(2**self._reconnect_count, 60) # Max 60 seconds
277
- jitter = base_delay * 0.1 # 10% jitter
278
- delay = base_delay + (jitter * (0.5 - asyncio.get_event_loop().time() % 1))
279
-
280
- self.logger.info(
281
- f"Attempting WebSocket reconnection #{self._reconnect_count} in {delay:.2f}s"
282
- )
283
-
284
- await asyncio.sleep(delay)
285
-
286
- try:
287
- # Disconnect first if needed
288
- if self._connection_established:
289
- await self.disconnect()
290
-
291
- # Attempt new connection
292
- await self.connect()
293
-
294
- self.logger.info(f"WebSocket reconnection #{self._reconnect_count} successful")
295
-
296
- except Exception as e:
297
- self.logger.error(f"WebSocket reconnection #{self._reconnect_count} failed: {e}")
298
- raise WebSocketError(f"Reconnection failed: {e}")
299
-
300
- async def send_response(self, response: Union[SuccessResponse, ErrorResponse]) -> None:
301
- """
302
- Send command response back to server.
303
-
304
- Args:
305
- response: Command response to send
306
-
307
- Raises:
308
- WebSocketError: If sending fails
309
- """
310
- if not self.is_connected():
311
- raise WebSocketError("Not connected to WebSocket server")
312
-
313
- try:
314
- # Convert response to dict for transmission
315
- response_data = response.model_dump()
316
-
317
- await self._client.emit(SocketEvent.COMMAND_RESPONSE, response_data)
318
-
319
- self.logger.debug(f"Sent response: {response.success}")
320
-
321
- except Exception as e:
322
- self.logger.error(f"Failed to send response: {e}")
323
- raise WebSocketError(f"Failed to send response: {e}")
324
-
325
- async def send_log(self, log_request: LoggingRequest) -> None:
326
- """
327
- Send log entry to server.
328
-
329
- Args:
330
- log_request: Log entry to send
331
-
332
- Raises:
333
- WebSocketError: If sending fails
334
- """
335
- if not self.is_connected():
336
- # Don't raise error for logging - just skip
337
- self.logger.debug("Skipping log transmission - not connected")
338
- return
339
-
340
- try:
341
- # Convert log request to dict for transmission
342
- log_data = log_request.model_dump()
343
-
344
- await self._client.emit(SocketEvent.LOG_ENTRY, log_data)
345
-
346
- self.logger.debug(f"Sent log entry: {log_request.level}")
347
-
348
- except Exception as e:
349
- self.logger.error(f"Failed to send log entry: {e}")
350
- # Don't raise error for logging failures
351
-
352
- def set_command_handler(
353
- self, handler: Callable[[ParserCommandEvent], Union[None, Awaitable[None]]]
354
- ) -> None:
355
- """
356
- Set command handler function.
357
-
358
- Args:
359
- handler: Function to handle incoming commands
360
- """
361
- self._command_handler = handler
362
- self.logger.debug("Command handler registered")
363
-
364
- def set_connection_handler(
365
- self, handler: Callable[[str, Any], Union[None, Awaitable[None]]]
366
- ) -> None:
367
- """
368
- Set connection event handler function.
369
-
370
- Args:
371
- handler: Function to handle connection events
372
- """
373
- self._connection_handler = handler
374
- self.logger.debug("Connection handler registered")
375
-
376
- def is_connected(self) -> bool:
377
- """Check if WebSocket is connected."""
378
- # TEMPORARY FIX: Only check our internal flag, not auto-generated client flag
379
- # The auto-generated client's .connected flag becomes False incorrectly
380
- return self._connection_established
381
-
382
- def get_connection_state(self) -> WebSocketStateInfo:
383
- """Get current connection state as type-safe Pydantic model."""
384
- # Build state from our internal tracking (no raw dict usage)
385
- return WebSocketStateInfo(
386
- status=WebSocketConnectionState.CONNECTED if self.is_connected() else WebSocketConnectionState.DISCONNECTED,
387
- session_id=self.parser_id,
388
- last_ping=self._last_ping.isoformat() if self._last_ping else None,
389
- connection_time=getattr(self, "_connection_time", None),
390
- connected=self.is_connected(),
391
- connecting=getattr(self, "_connecting", False),
392
- error=None, # Could be extended to track last error
393
- last_connected=self._last_ping.isoformat() if self._last_ping else None,
394
- reconnect_count=self._reconnect_count,
395
- )
396
-
397
- async def health_check(self) -> WebSocketStateInfo:
398
- """
399
- Perform health check of WebSocket connection.
400
-
401
- Returns:
402
- Type-safe WebSocketStateInfo model (NO raw Dict usage!)
403
- """
404
- return self.get_connection_state()
405
-
406
- def get_statistics(self) -> ConnectionStats:
407
- """
408
- Get WebSocket connection statistics.
409
-
410
- Returns:
411
- ConnectionStats with typed connection statistics
412
- """
413
- return ConnectionStats(
414
- total_connections=1 if self.is_connected() else 0,
415
- parser_connections=1 if self.is_connected() else 0,
416
- client_connections=1 if self.is_connected() else 0,
417
- active_rooms=0, # Client doesn't track rooms
418
- max_connections=1, # Single client connection
419
- metrics=None, # Can be extended later
420
- )