unrealon 2.0.5__py3-none-any.whl → 2.0.7__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.
- {unrealon-2.0.5.dist-info → unrealon-2.0.7.dist-info}/METADATA +1 -1
- {unrealon-2.0.5.dist-info → unrealon-2.0.7.dist-info}/RECORD +15 -14
- unrealon_core/__init__.py +10 -1
- unrealon_core/enums/types.py +1 -0
- unrealon_core/models/websocket/__init__.py +13 -1
- unrealon_core/models/websocket/broadcast.py +168 -0
- unrealon_driver/driver/communication/session.py +12 -3
- unrealon_driver/driver/communication/websocket_client.py +17 -12
- unrealon_driver/driver/lifecycle/daemon.py +1 -0
- unrealon_driver/driver/lifecycle/initialization.py +14 -1
- unrealon_driver/managers/logger.py +5 -0
- {unrealon-2.0.5.dist-info → unrealon-2.0.7.dist-info}/LICENSE +0 -0
- {unrealon-2.0.5.dist-info → unrealon-2.0.7.dist-info}/WHEEL +0 -0
- {unrealon-2.0.5.dist-info → unrealon-2.0.7.dist-info}/entry_points.txt +0 -0
- {unrealon-2.0.5.dist-info → unrealon-2.0.7.dist-info}/top_level.txt +0 -0
|
@@ -28,14 +28,14 @@ unrealon_browser/stealth/nodriver_stealth.pyc,sha256=SnDMdeG_W2LDK_3UfrjDeolMpqx
|
|
|
28
28
|
unrealon_browser/stealth/playwright_stealth.pyc,sha256=Y-IiRTu136R6LIstGdKbns1j-CODX3sTGVT0IGx_MF4,6529
|
|
29
29
|
unrealon_browser/stealth/scanner_tester.pyc,sha256=ki_Lp7zBp12iWgj3LGPnXTwemwgaGG1UrWeM1IXB6Gs,21711
|
|
30
30
|
unrealon_browser/stealth/undetected_chrome.pyc,sha256=HNp2_84zwp-JG-Y3jqQwCNldnG6P5bBnbf9dBV_pOuw,12765
|
|
31
|
-
unrealon_core/__init__.py,sha256=
|
|
31
|
+
unrealon_core/__init__.py,sha256=ZAinyQDsAS63xqnl5uqUKTna9M-xFDs6fLwy8-Hh-X0,5599
|
|
32
32
|
unrealon_core/version.py,sha256=qZOlKA_Hsz7_KXsCLO_0l9Mf0u_iNTxvHZPV21DwCqs,5803
|
|
33
33
|
unrealon_core/config/__init__.py,sha256=57-KZaTDya0oyfOCfZ3pU1xLLbnZPBgqwfP9VrfhcKE,395
|
|
34
34
|
unrealon_core/config/environment.py,sha256=TACbyjr3lxrA9R_Ve0LLqyLnRk3FShm2imQjhiP9i98,4589
|
|
35
35
|
unrealon_core/config/urls.py,sha256=7ScpWEhSu1kewhMaKhuqgiMHIv_fyI1TyRiS-f2wrLo,2821
|
|
36
36
|
unrealon_core/enums/__init__.py,sha256=C-fqNVSWofnaq2Ed6GbGtck8WkN8gpHYA_NiIlaEbTI,520
|
|
37
37
|
unrealon_core/enums/status.py,sha256=DT6rth7Ve7chsYhJtccY6plsgQQ8jEMhfhcZTpK308c,6861
|
|
38
|
-
unrealon_core/enums/types.py,sha256=
|
|
38
|
+
unrealon_core/enums/types.py,sha256=o4df_zPVE5ByF4P5t_dnwmr1GVQytl5ppKNQBCu0i2A,8784
|
|
39
39
|
unrealon_core/error_handling/__init__.py,sha256=s7VXUJG7nvD6Od76-ZfFmn5e6r29mxNusP8YPba73GM,1248
|
|
40
40
|
unrealon_core/error_handling/circuit_breaker.py,sha256=IPT7I8nrDm4eDojrjMgM3-vLIaz-0raS-9W3LUpFnhY,10066
|
|
41
41
|
unrealon_core/error_handling/error_context.py,sha256=jfluYy1FVyyU_8dwjBN1w2vPq9oLRYLg2fgndlc_8As,9798
|
|
@@ -61,8 +61,9 @@ unrealon_core/models/logging.py,sha256=MKGjMmhJhediGNVKmX0wfm1GO2kfvEqOp2cCfq42V
|
|
|
61
61
|
unrealon_core/models/task.py,sha256=QSOQMXNbvD7vfP6ddYUBPwD7jj0N9_zQxjwDMrznXo4,435
|
|
62
62
|
unrealon_core/models/typed_responses.py,sha256=shEvV4A7mYUKIzG3zD4zoRO2PmVLL3iLtGjzRGSW8Ks,7034
|
|
63
63
|
unrealon_core/models/websocket_session.py,sha256=q3RXQP2CwRTgUTYMRnb4xzzdGWUOeL8maYxVFPmF92w,5119
|
|
64
|
-
unrealon_core/models/websocket/__init__.py,sha256=
|
|
64
|
+
unrealon_core/models/websocket/__init__.py,sha256=wBgv1ZI_0_SiC2AX-UOA5fivi4rf3GEFhLDG159-x_s,2845
|
|
65
65
|
unrealon_core/models/websocket/base.py,sha256=gmkJ-vLpsajc4aGlPBeMURIFNg3AgX4yYSnJQAqqkf0,1388
|
|
66
|
+
unrealon_core/models/websocket/broadcast.py,sha256=XoefNORneicJUQxutFkzuPJDEAEyQlZEWtmBqL97yVg,4126
|
|
66
67
|
unrealon_core/models/websocket/config.py,sha256=AZz9wK8j0UIkRkDE17Nsxdocimh-41MJQkS-_VzTnM0,4665
|
|
67
68
|
unrealon_core/models/websocket/driver.py,sha256=Bi1B7nSSWkLFCwfIOLJSkPUxGS5r9x4Mw9XWvHuSxa0,5206
|
|
68
69
|
unrealon_core/models/websocket/errors.py,sha256=l5w1rCx_RrzdISPwLOoKtoPCuSNjHL5XExyFaHgayS4,3095
|
|
@@ -92,16 +93,16 @@ unrealon_driver/decorators/task.py,sha256=nnG-S99BSdtKYXZ97XBkQLDc-jpc4a6SKv-6b7
|
|
|
92
93
|
unrealon_driver/decorators/timing.py,sha256=Bmtsp2tWxY4EOq3onF1OTSk0rqf9lQNlX4RL-hyr4ZM,3927
|
|
93
94
|
unrealon_driver/driver/__init__.py,sha256=P_NJXcsigIjROwErqUXgS0VneUfGggFL4bWDbdB73iw,419
|
|
94
95
|
unrealon_driver/driver/communication/__init__.py,sha256=SalrzX_55WXlkbS9P6nm6PhddoI8pquURqx3103Q708,205
|
|
95
|
-
unrealon_driver/driver/communication/session.py,sha256=
|
|
96
|
-
unrealon_driver/driver/communication/websocket_client.py,sha256=
|
|
96
|
+
unrealon_driver/driver/communication/session.py,sha256=DYN_Q3Qm3XuOi-dM8aNihJfQJl7n8cgB1GHP621ZosQ,7552
|
|
97
|
+
unrealon_driver/driver/communication/websocket_client.py,sha256=VPsICBvGHunuCGZvorvPCF01Qdvp7QWyTDX0hkYXRwo,7910
|
|
97
98
|
unrealon_driver/driver/core/__init__.py,sha256=ZvJQp1zO7pj6tBNYTJk2fj-0ZMiQTQEk-I9hXalNsfg,235
|
|
98
99
|
unrealon_driver/driver/core/config.py,sha256=jWJjRll19VlL4iM5Q-J3o9qwYeH89Iuj1_3KayM6fCk,5914
|
|
99
100
|
unrealon_driver/driver/core/driver.py,sha256=NI-pdhnduRyHLsfFr8HmP2gp7pR1pWB4vBIJkMJ2cls,7886
|
|
100
101
|
unrealon_driver/driver/factory/__init__.py,sha256=XrjBhOaLvC3MIG5PAFIYS_xYXFDz5JizpFvmQcwA7mU,189
|
|
101
102
|
unrealon_driver/driver/factory/manager_factory.py,sha256=zJt63N8oWNJS0aNbLy7WjY4GCeUwLjvtWGdqdpucufU,4792
|
|
102
103
|
unrealon_driver/driver/lifecycle/__init__.py,sha256=KnkXklezAOIbXcCzEU_XSOt32z7tz1zIGclXYXTkO8k,286
|
|
103
|
-
unrealon_driver/driver/lifecycle/daemon.py,sha256=
|
|
104
|
-
unrealon_driver/driver/lifecycle/initialization.py,sha256=
|
|
104
|
+
unrealon_driver/driver/lifecycle/daemon.py,sha256=KHAzpiWFu3HRElRtzSEStmI74bMivFjfCAFlXha87KU,2609
|
|
105
|
+
unrealon_driver/driver/lifecycle/initialization.py,sha256=R4MgfkSNnfAdMO0Kp1Cx42cfNqq8VIxj_mGX7ECXad4,4406
|
|
105
106
|
unrealon_driver/driver/lifecycle/shutdown.py,sha256=h-6hKjDP30OjKiSgLe3UIfpS5wDbQFRaYWnEPosyTe0,1426
|
|
106
107
|
unrealon_driver/driver/monitoring/__init__.py,sha256=MJjLm4b5pzSpXGOq50e-MKUkyToiUbARzkGqNqN-iJg,162
|
|
107
108
|
unrealon_driver/driver/monitoring/health.py,sha256=rOH0wChDBTnDbV7MstB21JsJJUMGMeq3crb47RLL2ek,2164
|
|
@@ -113,16 +114,16 @@ unrealon_driver/managers/base.py,sha256=GkuXillg9uqqnx6RL682fmKgK-7JyqYlH6DFUgyN
|
|
|
113
114
|
unrealon_driver/managers/browser.py,sha256=9kwdmWPxWFpNQ1KejtpzdN615V8PBJu8Y2nUOewQaeQ,3489
|
|
114
115
|
unrealon_driver/managers/cache.py,sha256=c0tPKQ5KFd_Un1U8mw3j1WPuycxg863MMWNMveVF_2I,3506
|
|
115
116
|
unrealon_driver/managers/http.py,sha256=EjlpoTRuhpsgzzrEARxRlbGczzua7hnKFVq06bvCgTM,3624
|
|
116
|
-
unrealon_driver/managers/logger.py,sha256=
|
|
117
|
+
unrealon_driver/managers/logger.py,sha256=PL3rA9ZQl12jJU0EiPAkLwJ6eDHQfIzr8-nc8bVivKQ,10526
|
|
117
118
|
unrealon_driver/managers/proxy.py,sha256=Y_3ok2iGefeYHcTtBQIEK3Rnr8qRnPsP90hOOYPUMz0,3449
|
|
118
119
|
unrealon_driver/managers/registry.py,sha256=--oNPU-65e8J21ubJufyEOc1TirnzJIvpvuY_j7rH7Q,2666
|
|
119
120
|
unrealon_driver/managers/threading.py,sha256=djw5cSC99dfBKmep3IJ_8IgxQceMXtNvCp5fIxHM0TY,1702
|
|
120
121
|
unrealon_driver/managers/update.py,sha256=-hohVxGXpj5bZ6ZTQN6NH1RK9Pd6GVzCMtu3GS2SdcQ,3582
|
|
121
122
|
unrealon_driver/utils/__init__.py,sha256=qxXVoQJVdLJhaLBXk_LZV_062AhrvBrMPXWAKfEc3C4,104
|
|
122
123
|
unrealon_driver/utils/time.py,sha256=Oxk1eicKeZl8ZWbf7gu1Ll716k6CpXmVj67FHSnPIsA,184
|
|
123
|
-
unrealon-2.0.
|
|
124
|
-
unrealon-2.0.
|
|
125
|
-
unrealon-2.0.
|
|
126
|
-
unrealon-2.0.
|
|
127
|
-
unrealon-2.0.
|
|
128
|
-
unrealon-2.0.
|
|
124
|
+
unrealon-2.0.7.dist-info/LICENSE,sha256=eEH8mWZW49YMpl4Sh5MtKqkZ8aVTzKQXiNPEnvL14ns,1070
|
|
125
|
+
unrealon-2.0.7.dist-info/METADATA,sha256=6emT2rPYUexfKJNIKu4CuuhuSCYptvwMahqhmiXqzRs,15688
|
|
126
|
+
unrealon-2.0.7.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
|
|
127
|
+
unrealon-2.0.7.dist-info/entry_points.txt,sha256=k0qM-eotpajkKUq-almJmxj9afhXprZ6IkvQkSdcKhI,104
|
|
128
|
+
unrealon-2.0.7.dist-info/top_level.txt,sha256=Gu8IeIfIVfUxdi-h-F0nKMQxo15pjhHZ0aTadXTpRE8,47
|
|
129
|
+
unrealon-2.0.7.dist-info/RECORD,,
|
unrealon_core/__init__.py
CHANGED
|
@@ -42,7 +42,10 @@ from .models.communication import (
|
|
|
42
42
|
create_error_message, create_ack_message,
|
|
43
43
|
# Data models for strict typing
|
|
44
44
|
TaskAssignmentData, TaskResultData,
|
|
45
|
-
DriverRegistrationData, HeartbeatData, LogEntryData, LogContext
|
|
45
|
+
DriverRegistrationData, HeartbeatData, LogEntryData, LogContext,
|
|
46
|
+
# Broadcast models
|
|
47
|
+
DriverBroadcastData, DriverRegisterBroadcast,
|
|
48
|
+
DriverHeartbeatBroadcast, DriverDisconnectBroadcast
|
|
46
49
|
)
|
|
47
50
|
from .enums.status import DriverStatus, TaskStatus, ProxyStatus, LogLevel
|
|
48
51
|
from .enums.types import MessageType, ProxyType, TaskPriority
|
|
@@ -127,6 +130,12 @@ __all__ = [
|
|
|
127
130
|
"LogEntryData",
|
|
128
131
|
"LogContext",
|
|
129
132
|
|
|
133
|
+
# Broadcast models
|
|
134
|
+
"DriverBroadcastData",
|
|
135
|
+
"DriverRegisterBroadcast",
|
|
136
|
+
"DriverHeartbeatBroadcast",
|
|
137
|
+
"DriverDisconnectBroadcast",
|
|
138
|
+
|
|
130
139
|
# Status enums
|
|
131
140
|
"DriverStatus",
|
|
132
141
|
"TaskStatus",
|
unrealon_core/enums/types.py
CHANGED
|
@@ -38,6 +38,12 @@ from .proxy import (
|
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
from .utils import create_error_message, create_ack_message
|
|
41
|
+
from .broadcast import (
|
|
42
|
+
DriverBroadcastData,
|
|
43
|
+
DriverRegisterBroadcast,
|
|
44
|
+
DriverHeartbeatBroadcast,
|
|
45
|
+
DriverDisconnectBroadcast
|
|
46
|
+
)
|
|
41
47
|
|
|
42
48
|
__all__ = [
|
|
43
49
|
# Base
|
|
@@ -87,5 +93,11 @@ __all__ = [
|
|
|
87
93
|
|
|
88
94
|
# Utilities
|
|
89
95
|
'create_error_message',
|
|
90
|
-
'create_ack_message'
|
|
96
|
+
'create_ack_message',
|
|
97
|
+
|
|
98
|
+
# Broadcast messages
|
|
99
|
+
'DriverBroadcastData',
|
|
100
|
+
'DriverRegisterBroadcast',
|
|
101
|
+
'DriverHeartbeatBroadcast',
|
|
102
|
+
'DriverDisconnectBroadcast'
|
|
91
103
|
]
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Broadcast WebSocket Models.
|
|
3
|
+
|
|
4
|
+
Strictly typed models for broadcasting driver events to monitoring clients.
|
|
5
|
+
These are Server → Client messages for real-time monitoring.
|
|
6
|
+
|
|
7
|
+
Phase 2: Core Systems - WebSocket Bridge
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import List, Optional
|
|
11
|
+
from pydantic import Field, ConfigDict
|
|
12
|
+
|
|
13
|
+
from ..base import UnrealOnBaseModel
|
|
14
|
+
from .base import WebSocketMessage, MessageType
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DriverBroadcastData(UnrealOnBaseModel):
|
|
18
|
+
"""Driver broadcast data payload - strictly typed."""
|
|
19
|
+
|
|
20
|
+
model_config = ConfigDict(
|
|
21
|
+
validate_assignment=True,
|
|
22
|
+
extra="forbid"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
driver_id: str = Field(
|
|
26
|
+
description="Unique driver identifier",
|
|
27
|
+
min_length=1
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
driver_type: str = Field(
|
|
31
|
+
description="Type of driver (e.g., 'universal', 'ecommerce')",
|
|
32
|
+
min_length=1
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
status: str = Field(
|
|
36
|
+
default="active",
|
|
37
|
+
pattern=r"^(active|idle|busy|offline|error)$",
|
|
38
|
+
description="Current driver status"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
capabilities: List[str] = Field(
|
|
42
|
+
default_factory=list,
|
|
43
|
+
description="List of supported task types"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
active_tasks: int = Field(
|
|
47
|
+
default=0,
|
|
48
|
+
ge=0,
|
|
49
|
+
description="Number of currently active tasks"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
completed_tasks: int = Field(
|
|
53
|
+
default=0,
|
|
54
|
+
ge=0,
|
|
55
|
+
description="Total completed tasks since startup"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
failed_tasks: int = Field(
|
|
59
|
+
default=0,
|
|
60
|
+
ge=0,
|
|
61
|
+
description="Total failed tasks since startup"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
uptime_seconds: float = Field(
|
|
65
|
+
default=0.0,
|
|
66
|
+
ge=0.0,
|
|
67
|
+
description="Driver uptime in seconds"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
last_seen: Optional[str] = Field(
|
|
71
|
+
default=None,
|
|
72
|
+
description="ISO timestamp of last heartbeat"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
connected_at: Optional[str] = Field(
|
|
76
|
+
default=None,
|
|
77
|
+
description="ISO timestamp when driver connected"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
disconnected_at: Optional[str] = Field(
|
|
81
|
+
default=None,
|
|
82
|
+
description="ISO timestamp when driver disconnected"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Additional fields for complete driver information
|
|
86
|
+
version: Optional[str] = Field(
|
|
87
|
+
default=None,
|
|
88
|
+
description="Driver version"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
driver_name: Optional[str] = Field(
|
|
92
|
+
default=None,
|
|
93
|
+
description="Human-readable driver name"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
environment: Optional[str] = Field(
|
|
97
|
+
default=None,
|
|
98
|
+
description="Driver environment (development, production, etc.)"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
region: Optional[str] = Field(
|
|
102
|
+
default=None,
|
|
103
|
+
description="Driver region"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
max_concurrent_tasks: Optional[int] = Field(
|
|
107
|
+
default=None,
|
|
108
|
+
ge=1,
|
|
109
|
+
description="Maximum concurrent tasks"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
tags: List[str] = Field(
|
|
113
|
+
default_factory=list,
|
|
114
|
+
description="Driver tags"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class DriverRegisterBroadcast(WebSocketMessage):
|
|
119
|
+
"""Driver registration broadcast message (Server → Monitoring Clients)."""
|
|
120
|
+
|
|
121
|
+
model_config = ConfigDict(
|
|
122
|
+
validate_assignment=True,
|
|
123
|
+
extra="forbid"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
type: MessageType = Field(
|
|
127
|
+
default=MessageType.DRIVER_REGISTER
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
data: DriverBroadcastData = Field(
|
|
131
|
+
description="Driver registration broadcast data"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class DriverHeartbeatBroadcast(WebSocketMessage):
|
|
136
|
+
"""Driver heartbeat broadcast message (Server → Monitoring Clients)."""
|
|
137
|
+
|
|
138
|
+
model_config = ConfigDict(
|
|
139
|
+
validate_assignment=True,
|
|
140
|
+
extra="forbid"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
type: MessageType = Field(
|
|
144
|
+
default=MessageType.DRIVER_HEARTBEAT,
|
|
145
|
+
frozen=True
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
data: DriverBroadcastData = Field(
|
|
149
|
+
description="Driver heartbeat broadcast data"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class DriverDisconnectBroadcast(WebSocketMessage):
|
|
154
|
+
"""Driver disconnect broadcast message (Server → Monitoring Clients)."""
|
|
155
|
+
|
|
156
|
+
model_config = ConfigDict(
|
|
157
|
+
validate_assignment=True,
|
|
158
|
+
extra="forbid"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
type: MessageType = Field(
|
|
162
|
+
default=MessageType.DRIVER_DISCONNECT,
|
|
163
|
+
frozen=True
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
data: DriverBroadcastData = Field(
|
|
167
|
+
description="Driver disconnect broadcast data"
|
|
168
|
+
)
|
|
@@ -12,6 +12,7 @@ from pydantic import BaseModel, Field
|
|
|
12
12
|
|
|
13
13
|
from unrealon_core.models.websocket import (
|
|
14
14
|
TaskAssignmentData,
|
|
15
|
+
TaskAssignmentMessage,
|
|
15
16
|
TaskResultData,
|
|
16
17
|
WebSocketMessage
|
|
17
18
|
)
|
|
@@ -69,21 +70,26 @@ class DriverSession:
|
|
|
69
70
|
|
|
70
71
|
try:
|
|
71
72
|
# Connect WebSocket
|
|
73
|
+
logger.info(f"🔌 Connecting WebSocket for driver: {self.driver_id}")
|
|
72
74
|
self.status = SessionStatus.CONNECTING
|
|
73
75
|
if not await self.websocket_client.connect():
|
|
76
|
+
logger.error(f"❌ WebSocket connection failed for driver: {self.driver_id}")
|
|
74
77
|
self.status = SessionStatus.ERROR
|
|
75
78
|
return False
|
|
76
79
|
|
|
80
|
+
logger.info(f"✅ WebSocket connected for driver: {self.driver_id}")
|
|
77
81
|
self.status = SessionStatus.CONNECTED
|
|
78
82
|
self.stats.connected_at = utc_now()
|
|
79
83
|
|
|
80
84
|
# Register driver
|
|
85
|
+
logger.info(f"📝 Registering driver: {self.driver_id} with capabilities: {capabilities}")
|
|
81
86
|
if await self.register(capabilities or []):
|
|
82
87
|
self.status = SessionStatus.REGISTERED
|
|
83
88
|
self.stats.registered_at = utc_now()
|
|
84
|
-
logger.info(f"Session started for driver: {self.driver_id}")
|
|
89
|
+
logger.info(f"✅ Session started for driver: {self.driver_id}")
|
|
85
90
|
return True
|
|
86
91
|
else:
|
|
92
|
+
logger.error(f"❌ Driver registration failed for: {self.driver_id}")
|
|
87
93
|
self.status = SessionStatus.ERROR
|
|
88
94
|
return False
|
|
89
95
|
|
|
@@ -139,8 +145,11 @@ class DriverSession:
|
|
|
139
145
|
async def _handle_task_assignment(self, message: WebSocketMessage):
|
|
140
146
|
"""Handle task assignment."""
|
|
141
147
|
try:
|
|
142
|
-
#
|
|
143
|
-
|
|
148
|
+
# Parse as TaskAssignmentMessage
|
|
149
|
+
|
|
150
|
+
# Convert to proper task assignment message
|
|
151
|
+
task_message = TaskAssignmentMessage.model_validate(message.model_dump())
|
|
152
|
+
task_data = task_message.data
|
|
144
153
|
|
|
145
154
|
# Find handler
|
|
146
155
|
handler = self.task_handlers.get(task_data.task_type)
|
|
@@ -40,9 +40,11 @@ class WebSocketClient:
|
|
|
40
40
|
- Clean error handling
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
|
-
def __init__(self, websocket_url: str, driver_id: str):
|
|
43
|
+
def __init__(self, websocket_url: str, driver_id: str, custom_logger=None):
|
|
44
44
|
self.websocket_url = websocket_url
|
|
45
45
|
self.driver_id = driver_id
|
|
46
|
+
# Use custom logger if provided, otherwise use default
|
|
47
|
+
self._logger = custom_logger if custom_logger else logger
|
|
46
48
|
self.websocket: Optional[ClientConnection] = None
|
|
47
49
|
self.connected = False
|
|
48
50
|
self.running = False
|
|
@@ -94,20 +96,20 @@ class WebSocketClient:
|
|
|
94
96
|
self.websocket = None
|
|
95
97
|
|
|
96
98
|
self.connected = False
|
|
97
|
-
|
|
99
|
+
self._logger.info("WebSocket client stopped")
|
|
98
100
|
|
|
99
101
|
async def _establish_connection(self) -> bool:
|
|
100
102
|
"""Establish WebSocket connection."""
|
|
101
103
|
try:
|
|
102
|
-
|
|
104
|
+
self._logger.info(f"Connecting to WebSocket: {self.websocket_url}")
|
|
103
105
|
self.websocket = await websockets.connect(self.websocket_url)
|
|
104
106
|
self.connected = True
|
|
105
107
|
self.reconnect_attempts = 0
|
|
106
108
|
self.reconnect_delay = 1.0
|
|
107
|
-
|
|
109
|
+
self._logger.info("WebSocket connected successfully")
|
|
108
110
|
return True
|
|
109
111
|
except Exception as e:
|
|
110
|
-
|
|
112
|
+
self._logger.error(f"WebSocket connection failed: {e}")
|
|
111
113
|
self.connected = False
|
|
112
114
|
return False
|
|
113
115
|
|
|
@@ -115,10 +117,10 @@ class WebSocketClient:
|
|
|
115
117
|
"""Monitor connection and handle reconnection."""
|
|
116
118
|
while self.running:
|
|
117
119
|
if not self.connected and self.running:
|
|
118
|
-
|
|
120
|
+
self._logger.info(f"Attempting reconnection (attempt {self.reconnect_attempts + 1})")
|
|
119
121
|
|
|
120
122
|
if await self._establish_connection():
|
|
121
|
-
|
|
123
|
+
self._logger.info("Reconnection successful")
|
|
122
124
|
else:
|
|
123
125
|
self.reconnect_attempts += 1
|
|
124
126
|
# Exponential backoff
|
|
@@ -136,13 +138,16 @@ class WebSocketClient:
|
|
|
136
138
|
if self.connected and self.websocket and self.message_queue:
|
|
137
139
|
try:
|
|
138
140
|
message = self.message_queue.popleft()
|
|
141
|
+
self._logger.info(f"📤 Sending WebSocket message: {message[:200]}...") # Log first 200 chars
|
|
139
142
|
await self.websocket.send(message)
|
|
143
|
+
self._logger.info(f"✅ Message sent successfully")
|
|
140
144
|
except (websockets.exceptions.ConnectionClosed, ConnectionResetError):
|
|
141
145
|
self.connected = False
|
|
142
146
|
# Put message back in queue
|
|
143
147
|
self.message_queue.appendleft(message)
|
|
148
|
+
self._logger.warning("🔌 Connection lost, message queued for retry")
|
|
144
149
|
except Exception as e:
|
|
145
|
-
|
|
150
|
+
self._logger.error(f"❌ Error sending message: {e}")
|
|
146
151
|
else:
|
|
147
152
|
await asyncio.sleep(0.1)
|
|
148
153
|
|
|
@@ -163,9 +168,9 @@ class WebSocketClient:
|
|
|
163
168
|
|
|
164
169
|
except (websockets.exceptions.ConnectionClosed, ConnectionResetError):
|
|
165
170
|
self.connected = False
|
|
166
|
-
|
|
171
|
+
self._logger.warning("WebSocket connection lost")
|
|
167
172
|
except Exception as e:
|
|
168
|
-
|
|
173
|
+
self._logger.error(f"Error receiving message: {e}")
|
|
169
174
|
else:
|
|
170
175
|
await asyncio.sleep(0.1)
|
|
171
176
|
|
|
@@ -197,9 +202,9 @@ class WebSocketClient:
|
|
|
197
202
|
# Queue for sending
|
|
198
203
|
self.send(registration_message)
|
|
199
204
|
|
|
200
|
-
|
|
205
|
+
self._logger.info(f"Driver registration queued: {self.driver_id}")
|
|
201
206
|
return True
|
|
202
207
|
|
|
203
208
|
except Exception as e:
|
|
204
|
-
|
|
209
|
+
self._logger.error(f"Driver registration failed: {e}")
|
|
205
210
|
return False
|
|
@@ -47,6 +47,7 @@ class DaemonManager:
|
|
|
47
47
|
|
|
48
48
|
try:
|
|
49
49
|
# Initialize driver with capabilities
|
|
50
|
+
logger.info(f"🎯 Daemon initializing driver with capabilities: {driver.capabilities}")
|
|
50
51
|
success = await DriverInitializer.initialize_driver(driver, driver.capabilities)
|
|
51
52
|
if not success:
|
|
52
53
|
raise RuntimeError("Driver initialization failed")
|
|
@@ -10,6 +10,8 @@ from typing import List, TYPE_CHECKING
|
|
|
10
10
|
from ..core.config import DriverMode
|
|
11
11
|
from ..communication.websocket_client import WebSocketClient
|
|
12
12
|
from ..communication.session import DriverSession
|
|
13
|
+
from unrealon_core.config.environment import get_environment_config
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
if TYPE_CHECKING:
|
|
15
17
|
from ..core.driver import UniversalDriver
|
|
@@ -37,6 +39,14 @@ class DriverInitializer:
|
|
|
37
39
|
|
|
38
40
|
try:
|
|
39
41
|
logger.info(f"Initializing UniversalDriver: {driver.driver_id}")
|
|
42
|
+
logger.info(f"🔧 Driver mode: {driver.config.mode}")
|
|
43
|
+
logger.info(f"📡 WebSocket URL: {driver.config.effective_websocket_url}")
|
|
44
|
+
logger.info(f"🎯 Capabilities: {capabilities}")
|
|
45
|
+
|
|
46
|
+
# Log environment info if available
|
|
47
|
+
env_config = get_environment_config()
|
|
48
|
+
logger.info(f"🌐 Environment: {env_config.environment.value}")
|
|
49
|
+
print(f"🌐 Environment: {env_config.environment}")
|
|
40
50
|
|
|
41
51
|
# Initialize manager system
|
|
42
52
|
if not await driver.manager_registry.initialize_all():
|
|
@@ -65,9 +75,12 @@ class DriverInitializer:
|
|
|
65
75
|
|
|
66
76
|
# Setup WebSocket client if URL available
|
|
67
77
|
if websocket_url:
|
|
78
|
+
# Pass driver's logger to WebSocket client for unified logging
|
|
79
|
+
custom_logger = driver.logger_manager.local_logger if driver.logger_manager else None
|
|
68
80
|
driver.websocket_client = WebSocketClient(
|
|
69
81
|
websocket_url,
|
|
70
|
-
driver.driver_id
|
|
82
|
+
driver.driver_id,
|
|
83
|
+
custom_logger=custom_logger
|
|
71
84
|
)
|
|
72
85
|
|
|
73
86
|
# Set WebSocket client for logger (always for logging)
|
|
@@ -89,6 +89,11 @@ class LoggerManager(BaseManager):
|
|
|
89
89
|
self.local_logger.addHandler(handler)
|
|
90
90
|
self.local_logger.setLevel(getattr(logging, self.config.log_level))
|
|
91
91
|
|
|
92
|
+
# Also configure root unrealon_driver logger to use same handler
|
|
93
|
+
unrealon_logger = logging.getLogger('unrealon_driver')
|
|
94
|
+
unrealon_logger.addHandler(handler)
|
|
95
|
+
unrealon_logger.setLevel(getattr(logging, self.config.log_level))
|
|
96
|
+
|
|
92
97
|
except Exception as e:
|
|
93
98
|
logger.error(f"Failed to setup local logging: {e}")
|
|
94
99
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|