unrealon 2.0.4__py3-none-any.whl → 2.0.6__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unrealon
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Enterprise-grade web scraping platform with AI-powered automation and real-time orchestration capabilities
5
5
  Author-email: UnrealOn Team <team@unrealon.com>
6
6
  License: MIT
@@ -1,15 +1,15 @@
1
1
  unrealon_browser/README.md,sha256=9pP6RrfMGHtdT5uDLFAUB1e4nNGzZudXViEo1940gKw,396
2
2
  unrealon_browser/__init__.py,sha256=aYEmGQyhGEwcr-XPKqWJb21uQPB9XvqwZgKSSwkbb_I,1521
3
3
  unrealon_browser/cli/__init__.py,sha256=b3r88oeCYsqZF8EU8EZXP9v54Q8cIimN7UmxJsXcB84,264
4
- unrealon_browser/cli/browser_cli.py,sha256=dQ7p3Ml1touWbkbo-U4jkhknhRvAYT9mzbe2ZTLylZ0,8505
4
+ unrealon_browser/cli/browser_cli.py,sha256=KobEb9nhPEHDmB5K67LQNpMvuA_fDNrVfq9w9JWpgHI,8510
5
5
  unrealon_browser/cli/cookies_cli.py,sha256=yhZvGrg8bknlH4zlySdi8ue-25Ue-1rI_u1G06OIMg4,13304
6
- unrealon_browser/cli/interactive_mode.py,sha256=sXjiGZi-BK-Q5KhxYs8HJZ2EqkQK0Jx7MhtVnULRqLg,12120
6
+ unrealon_browser/cli/interactive_mode.py,sha256=gLn9bMH0h0tPX3dP4i4QQxQK4Htkyg5r4KcqdMBaP6Q,12125
7
7
  unrealon_browser/cli/main.py,sha256=XCYcTxJUqaz320KCU_JPKizYMk6bdljb8Boyok3uO-4,1353
8
8
  unrealon_browser/core/__init__.py,sha256=uVL_t4sZelUzflWPdgrwoXGnAkSV1WNQ98-eu0QB2eM,151
9
9
  unrealon_browser/core/browser_manager.py,sha256=9xxo0kqbUcssFBNpvIXavWBya2E3TmgHKplQQ2kkZeU,29598
10
10
  unrealon_browser/dto/__init__.py,sha256=bApqcLz-KanEi0_MCiFPrQmGBoX3VBijP7XtBUyIfjo,1636
11
11
  unrealon_browser/dto/bot_detection.py,sha256=qXfC0HghV7m4L6qA87t3STi-166jM-QgoP6OYbCb4o4,6884
12
- unrealon_browser/dto/models/config.py,sha256=krNAqzlEk0HnrmZRoTdfuKoDWnuXwv3pGl0mcFwr4zs,1747
12
+ unrealon_browser/dto/models/config.py,sha256=Why5H3rtFclmwbdczuDfhlgf-LDz72Aa8LhDX4_ayfw,1752
13
13
  unrealon_browser/dto/models/core.py,sha256=HvbwYG27rmmWtp401uws7lfalN_9QPad0M6ceCiN5iQ,2741
14
14
  unrealon_browser/dto/models/dataclasses.py,sha256=zqhJVyzp4CvtuTBsZwm6n6TodVWrZf9gkdDG-0_tgeA,2571
15
15
  unrealon_browser/dto/models/detection.py,sha256=ma9ZNIjPR7HnjqZaAj6ZoskiewPFiSn_FgFXSkgiQc8,2715
@@ -23,19 +23,19 @@ unrealon_browser/managers/page_wait_manager.py,sha256=UyZqiSfkjzahrxp9x1odXFIT_s
23
23
  unrealon_browser/managers/profile.py,sha256=HjddlSeUry_65WPtF8CMkT7cfJ6X3Jap9kJaaZpwtAA,18956
24
24
  unrealon_browser/stealth/__init__.py,sha256=zUfkPPafYlPANLVQIy-Se11R_UjcJakUb3krCxxUK5Q,842
25
25
  unrealon_browser/stealth/bypass_techniques.pyc,sha256=Tys_I4tnJmL9aQLB1k1mL-4OtzedhpYTmW4XPEIb3cI,25790
26
- unrealon_browser/stealth/manager.pyc,sha256=JC9g-LWoKPo1QuY1LUIyMmFEDgZJjrFlLuA3KbctQ3U,21178
26
+ unrealon_browser/stealth/manager.pyc,sha256=prGC5fWE-T4ROGSVrc65CJ_qFpb8dScuN83FotZ1oj4,21183
27
27
  unrealon_browser/stealth/nodriver_stealth.pyc,sha256=SnDMdeG_W2LDK_3UfrjDeolMpqxTMDNjRbId_YC_cKA,15286
28
28
  unrealon_browser/stealth/playwright_stealth.pyc,sha256=Y-IiRTu136R6LIstGdKbns1j-CODX3sTGVT0IGx_MF4,6529
29
- unrealon_browser/stealth/scanner_tester.pyc,sha256=m5jUXySno0g9AScJt5dyjppkM0QXENX3Sh5W4fRR5ZA,21706
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=bFKK6AOQVb34OLq3RlduDokLjf4cR0q1_sWAK5GQ2js,4954
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
- unrealon_core/config/environment.py,sha256=VNPse_SU-hFd1rT3WTxZl65CsTxeaXWxcQuAvWv1TJI,2774
35
- unrealon_core/config/urls.py,sha256=dlQCZSz5NasA5A4v3ff9beVqOkXL5aCa_rt1VDNIs9Q,2751
34
+ unrealon_core/config/environment.py,sha256=TACbyjr3lxrA9R_Ve0LLqyLnRk3FShm2imQjhiP9i98,4589
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=hf1NkA2sBIfgtNHqdQPr7Uow_E2SeDGh1Jpxls0RFYg,8704
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
@@ -48,13 +48,12 @@ unrealon_core/exceptions/driver.py,sha256=YB3_oRgOMzD4cCSEhqpqpP5iD6ChbZmaOtnw4B
48
48
  unrealon_core/exceptions/proxy.py,sha256=oqy3gV8jha1a2JrOtbJU8zTpWq_XA8Ooou2cl4eHF0o,246
49
49
  unrealon_core/exceptions/task.py,sha256=uNSyJgZvBSHtimQ-ZLPjjDZrVzq6sXscJUQDkCmQ0No,285
50
50
  unrealon_core/exceptions/validation.py,sha256=f7nWbi5ag1nqo7kwN0QaXYNfRrIwHhYVNlKHGiyhuQ8,351
51
- unrealon_core/models/__init__.py,sha256=rSpjZ4PiOMgkQ1iocsr2zPA2ziSV9_7Fdg5XU6EXY1g,1699
51
+ unrealon_core/models/__init__.py,sha256=msWqpIVlqWb0mX3jAwX83i78hFIoqZj8XgE4TgL_uu4,1379
52
52
  unrealon_core/models/arq_context.py,sha256=9a6yJgdQ3ZifoCgEEiN90q5qRzQ9pk0ivHnowhzLF7c,8389
53
53
  unrealon_core/models/arq_responses.py,sha256=OYEIjLZ1iEoWEKAOqAuudYWT4I_ZVeftDFOOmWjgEaM,4471
54
54
  unrealon_core/models/base.py,sha256=5x5Ie77wH_qRrezd8kSQ23DgOffSmCmICmVqEeXX4Hc,8964
55
55
  unrealon_core/models/bridge_stats.py,sha256=trVoAQkFG5fc8TSzUmH133Xwf8htKYM5Xyl_3-5ApnE,1878
56
56
  unrealon_core/models/communication.py,sha256=YFdiR-J0ncjmvg4yudU1bTfR61BEmV6sQ1zCXWN_xR0,1152
57
- unrealon_core/models/config.py,sha256=VFOFyjAdDVqNMVUruIeqdbOvo-_FvXhCtt9LQvPOijE,1355
58
57
  unrealon_core/models/connection_stats.py,sha256=KngZoi78WXsLAvl9ZYq6xRoVUaTBUVmnI8hrxZ8y038,1522
59
58
  unrealon_core/models/driver.py,sha256=RVl69fPFWW-E9yINUi2yXEWcw3sycc-bgVOw00VfkdU,690
60
59
  unrealon_core/models/driver_details.py,sha256=0Bc1J16Zika7p1SflsqssiF4IjpQbwNFij17H1pQR44,3737
@@ -62,8 +61,9 @@ unrealon_core/models/logging.py,sha256=MKGjMmhJhediGNVKmX0wfm1GO2kfvEqOp2cCfq42V
62
61
  unrealon_core/models/task.py,sha256=QSOQMXNbvD7vfP6ddYUBPwD7jj0N9_zQxjwDMrznXo4,435
63
62
  unrealon_core/models/typed_responses.py,sha256=shEvV4A7mYUKIzG3zD4zoRO2PmVLL3iLtGjzRGSW8Ks,7034
64
63
  unrealon_core/models/websocket_session.py,sha256=q3RXQP2CwRTgUTYMRnb4xzzdGWUOeL8maYxVFPmF92w,5119
65
- unrealon_core/models/websocket/__init__.py,sha256=F-KDDZAMJvCVQMo2Z-xLPQmG0B8JEQ2auxxI89ZCsro,2551
64
+ unrealon_core/models/websocket/__init__.py,sha256=wBgv1ZI_0_SiC2AX-UOA5fivi4rf3GEFhLDG159-x_s,2845
66
65
  unrealon_core/models/websocket/base.py,sha256=gmkJ-vLpsajc4aGlPBeMURIFNg3AgX4yYSnJQAqqkf0,1388
66
+ unrealon_core/models/websocket/broadcast.py,sha256=M4MycZvF88klW2RbZeeQD5xh2xKt7B7C59pqULC28oE,3366
67
67
  unrealon_core/models/websocket/config.py,sha256=AZz9wK8j0UIkRkDE17Nsxdocimh-41MJQkS-_VzTnM0,4665
68
68
  unrealon_core/models/websocket/driver.py,sha256=Bi1B7nSSWkLFCwfIOLJSkPUxGS5r9x4Mw9XWvHuSxa0,5206
69
69
  unrealon_core/models/websocket/errors.py,sha256=l5w1rCx_RrzdISPwLOoKtoPCuSNjHL5XExyFaHgayS4,3095
@@ -93,16 +93,16 @@ unrealon_driver/decorators/task.py,sha256=nnG-S99BSdtKYXZ97XBkQLDc-jpc4a6SKv-6b7
93
93
  unrealon_driver/decorators/timing.py,sha256=Bmtsp2tWxY4EOq3onF1OTSk0rqf9lQNlX4RL-hyr4ZM,3927
94
94
  unrealon_driver/driver/__init__.py,sha256=P_NJXcsigIjROwErqUXgS0VneUfGggFL4bWDbdB73iw,419
95
95
  unrealon_driver/driver/communication/__init__.py,sha256=SalrzX_55WXlkbS9P6nm6PhddoI8pquURqx3103Q708,205
96
- unrealon_driver/driver/communication/session.py,sha256=vRarQAUunmqltD1p2Z7Jms5xBK543XarfCUWAC_G8XQ,6936
97
- unrealon_driver/driver/communication/websocket_client.py,sha256=Msgu7n42tBMPBLhEHxlLxlHrDP1OFfhGReRSUPZKPsw,7163
96
+ unrealon_driver/driver/communication/session.py,sha256=DYN_Q3Qm3XuOi-dM8aNihJfQJl7n8cgB1GHP621ZosQ,7552
97
+ unrealon_driver/driver/communication/websocket_client.py,sha256=VPsICBvGHunuCGZvorvPCF01Qdvp7QWyTDX0hkYXRwo,7910
98
98
  unrealon_driver/driver/core/__init__.py,sha256=ZvJQp1zO7pj6tBNYTJk2fj-0ZMiQTQEk-I9hXalNsfg,235
99
- unrealon_driver/driver/core/config.py,sha256=YYvTlo6jNlNz-FKJ730nkhahlN4OSl7yz1txauC-NQ4,2848
99
+ unrealon_driver/driver/core/config.py,sha256=jWJjRll19VlL4iM5Q-J3o9qwYeH89Iuj1_3KayM6fCk,5914
100
100
  unrealon_driver/driver/core/driver.py,sha256=NI-pdhnduRyHLsfFr8HmP2gp7pR1pWB4vBIJkMJ2cls,7886
101
101
  unrealon_driver/driver/factory/__init__.py,sha256=XrjBhOaLvC3MIG5PAFIYS_xYXFDz5JizpFvmQcwA7mU,189
102
102
  unrealon_driver/driver/factory/manager_factory.py,sha256=zJt63N8oWNJS0aNbLy7WjY4GCeUwLjvtWGdqdpucufU,4792
103
103
  unrealon_driver/driver/lifecycle/__init__.py,sha256=KnkXklezAOIbXcCzEU_XSOt32z7tz1zIGclXYXTkO8k,286
104
- unrealon_driver/driver/lifecycle/daemon.py,sha256=6cglmGsMLmMgqkXm0cquzcQiUNLRJ2abrj37bJysIUA,2508
105
- unrealon_driver/driver/lifecycle/initialization.py,sha256=jwamdzG3IDKwYiTbMnGkBOJeWeTlPxIlQkOrsc22qCo,3649
104
+ unrealon_driver/driver/lifecycle/daemon.py,sha256=KHAzpiWFu3HRElRtzSEStmI74bMivFjfCAFlXha87KU,2609
105
+ unrealon_driver/driver/lifecycle/initialization.py,sha256=R4MgfkSNnfAdMO0Kp1Cx42cfNqq8VIxj_mGX7ECXad4,4406
106
106
  unrealon_driver/driver/lifecycle/shutdown.py,sha256=h-6hKjDP30OjKiSgLe3UIfpS5wDbQFRaYWnEPosyTe0,1426
107
107
  unrealon_driver/driver/monitoring/__init__.py,sha256=MJjLm4b5pzSpXGOq50e-MKUkyToiUbARzkGqNqN-iJg,162
108
108
  unrealon_driver/driver/monitoring/health.py,sha256=rOH0wChDBTnDbV7MstB21JsJJUMGMeq3crb47RLL2ek,2164
@@ -114,16 +114,16 @@ unrealon_driver/managers/base.py,sha256=GkuXillg9uqqnx6RL682fmKgK-7JyqYlH6DFUgyN
114
114
  unrealon_driver/managers/browser.py,sha256=9kwdmWPxWFpNQ1KejtpzdN615V8PBJu8Y2nUOewQaeQ,3489
115
115
  unrealon_driver/managers/cache.py,sha256=c0tPKQ5KFd_Un1U8mw3j1WPuycxg863MMWNMveVF_2I,3506
116
116
  unrealon_driver/managers/http.py,sha256=EjlpoTRuhpsgzzrEARxRlbGczzua7hnKFVq06bvCgTM,3624
117
- unrealon_driver/managers/logger.py,sha256=w-JiouSPN8YZKTgDshANv6EpiKEJ9r6R1vxQexQp32M,10243
117
+ unrealon_driver/managers/logger.py,sha256=PL3rA9ZQl12jJU0EiPAkLwJ6eDHQfIzr8-nc8bVivKQ,10526
118
118
  unrealon_driver/managers/proxy.py,sha256=Y_3ok2iGefeYHcTtBQIEK3Rnr8qRnPsP90hOOYPUMz0,3449
119
119
  unrealon_driver/managers/registry.py,sha256=--oNPU-65e8J21ubJufyEOc1TirnzJIvpvuY_j7rH7Q,2666
120
120
  unrealon_driver/managers/threading.py,sha256=djw5cSC99dfBKmep3IJ_8IgxQceMXtNvCp5fIxHM0TY,1702
121
121
  unrealon_driver/managers/update.py,sha256=-hohVxGXpj5bZ6ZTQN6NH1RK9Pd6GVzCMtu3GS2SdcQ,3582
122
122
  unrealon_driver/utils/__init__.py,sha256=qxXVoQJVdLJhaLBXk_LZV_062AhrvBrMPXWAKfEc3C4,104
123
123
  unrealon_driver/utils/time.py,sha256=Oxk1eicKeZl8ZWbf7gu1Ll716k6CpXmVj67FHSnPIsA,184
124
- unrealon-2.0.4.dist-info/LICENSE,sha256=eEH8mWZW49YMpl4Sh5MtKqkZ8aVTzKQXiNPEnvL14ns,1070
125
- unrealon-2.0.4.dist-info/METADATA,sha256=n8q2NabepEQ9LHwNHYyTsWWQ2njvdlWHC5Ry6mz9x9g,15688
126
- unrealon-2.0.4.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
127
- unrealon-2.0.4.dist-info/entry_points.txt,sha256=k0qM-eotpajkKUq-almJmxj9afhXprZ6IkvQkSdcKhI,104
128
- unrealon-2.0.4.dist-info/top_level.txt,sha256=Gu8IeIfIVfUxdi-h-F0nKMQxo15pjhHZ0aTadXTpRE8,47
129
- unrealon-2.0.4.dist-info/RECORD,,
124
+ unrealon-2.0.6.dist-info/LICENSE,sha256=eEH8mWZW49YMpl4Sh5MtKqkZ8aVTzKQXiNPEnvL14ns,1070
125
+ unrealon-2.0.6.dist-info/METADATA,sha256=i0-XIxaXmnkBInCUQVKkTLxp4Wh9fEGdL-4RvhIb12w,15688
126
+ unrealon-2.0.6.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
127
+ unrealon-2.0.6.dist-info/entry_points.txt,sha256=k0qM-eotpajkKUq-almJmxj9afhXprZ6IkvQkSdcKhI,104
128
+ unrealon-2.0.6.dist-info/top_level.txt,sha256=Gu8IeIfIVfUxdi-h-F0nKMQxo15pjhHZ0aTadXTpRE8,47
129
+ unrealon-2.0.6.dist-info/RECORD,,
@@ -16,7 +16,7 @@ from rich.table import Table
16
16
  from unrealon_browser.core.browser_manager import BrowserManager
17
17
  from unrealon_browser.dto.models.config import BrowserConfig, BrowserType, BrowserMode
18
18
 
19
- from unrealon_core.config import get_url_config
19
+ from unrealon_core.config.urls import get_url_config
20
20
 
21
21
  console = Console()
22
22
 
@@ -11,7 +11,7 @@ from rich.panel import Panel
11
11
  from rich.table import Table
12
12
  from typing import Dict, Any
13
13
 
14
- from unrealon_core.config import get_url_config
14
+ from unrealon_core.config.urls import get_url_config
15
15
 
16
16
  console = Console()
17
17
 
@@ -8,7 +8,7 @@ from typing import Optional
8
8
  from pydantic import BaseModel, Field, ConfigDict
9
9
  from .enums import BrowserType, BrowserMode
10
10
 
11
- from unrealon_core.config import get_url_config
11
+ from unrealon_core.config.urls import get_url_config
12
12
 
13
13
 
14
14
  def _get_default_stealth_url() -> str:
Binary file
Binary file
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
@@ -76,9 +79,19 @@ from .monitoring import (
76
79
  )
77
80
 
78
81
  # Configuration system
79
- from .config import (
80
- EnvironmentConfig, URLConfig,
81
- get_environment_config, get_url_config
82
+ from .config.environment import (
83
+ EnvironmentConfig, Environment,
84
+ get_environment_config, set_environment_config
85
+ )
86
+ from .config.urls import (
87
+ URLConfig,
88
+ get_url_config
89
+ )
90
+ from .models.websocket.config import (
91
+ DriverConfiguration,
92
+ LoggingConfiguration,
93
+ TaskConfiguration,
94
+ ProxyConfiguration
82
95
  )
83
96
 
84
97
  __all__ = [
@@ -117,6 +130,12 @@ __all__ = [
117
130
  "LogEntryData",
118
131
  "LogContext",
119
132
 
133
+ # Broadcast models
134
+ "DriverBroadcastData",
135
+ "DriverRegisterBroadcast",
136
+ "DriverHeartbeatBroadcast",
137
+ "DriverDisconnectBroadcast",
138
+
120
139
  # Status enums
121
140
  "DriverStatus",
122
141
  "TaskStatus",
@@ -155,6 +174,8 @@ __all__ = [
155
174
  "MonitoringDashboard", "get_system_overview",
156
175
 
157
176
  # Configuration system
158
- "EnvironmentConfig", "URLConfig",
159
- "get_environment_config", "get_url_config",
177
+ "EnvironmentConfig", "Environment", "URLConfig",
178
+ "get_environment_config", "set_environment_config", "get_url_config",
179
+ "DriverConfiguration", "LoggingConfiguration",
180
+ "TaskConfiguration", "ProxyConfiguration",
160
181
  ]
@@ -18,7 +18,7 @@ class Environment(str, Enum):
18
18
 
19
19
 
20
20
  class EnvironmentConfig(BaseModel):
21
- """Environment configuration settings."""
21
+ """Environment configuration settings with all system URLs and settings."""
22
22
 
23
23
  model_config = ConfigDict(
24
24
  # Add any specific config here if needed
@@ -39,6 +39,17 @@ class EnvironmentConfig(BaseModel):
39
39
  description="Logging level"
40
40
  )
41
41
 
42
+ # System URLs - environment-aware
43
+ redis_url: str = Field(
44
+ default_factory=lambda: os.getenv("REDIS_URL", "redis://localhost:6379/0"),
45
+ description="Redis connection URL"
46
+ )
47
+
48
+ max_workers: int = Field(
49
+ default_factory=lambda: int(os.getenv("MAX_WORKERS", "10")),
50
+ description="Maximum number of workers"
51
+ )
52
+
42
53
  @classmethod
43
54
  def from_env(cls) -> "EnvironmentConfig":
44
55
  """Create config from environment variables."""
@@ -76,6 +87,48 @@ class EnvironmentConfig(BaseModel):
76
87
  def is_testing(self) -> bool:
77
88
  """Check if running in testing mode."""
78
89
  return self.environment == Environment.TESTING
90
+
91
+ @property
92
+ def websocket_url(self) -> str:
93
+ """Get WebSocket URL based on environment."""
94
+ # Check explicit env var first
95
+ if ws_url := os.getenv("WEBSOCKET_URL"):
96
+ return ws_url
97
+
98
+ if self.is_production:
99
+ return "wss://ws.unrealon.com/ws"
100
+ elif self.is_development:
101
+ return "ws://localhost:8001/ws" # RPC server port
102
+ else: # testing
103
+ return "ws://localhost:8001/ws"
104
+
105
+ @property
106
+ def api_url(self) -> str:
107
+ """Get API URL based on environment."""
108
+ # Check explicit env var first
109
+ if api_url := os.getenv("API_URL"):
110
+ return api_url
111
+
112
+ if self.is_production:
113
+ return "https://api-m.unrealon.com"
114
+ elif self.is_development:
115
+ return "http://localhost:8002" # Backend server port
116
+ else: # testing
117
+ return "http://localhost:8002"
118
+
119
+ @property
120
+ def django_api_url(self) -> str:
121
+ """Get Django API URL based on environment."""
122
+ # Check explicit env var first
123
+ if api_url := os.getenv("DJANGO_API_URL"):
124
+ return api_url
125
+
126
+ if self.is_production:
127
+ return "https://api.unrealon.com"
128
+ elif self.is_development:
129
+ return "http://localhost:8000" # Django server port
130
+ else: # testing
131
+ return "http://localhost:8000"
79
132
 
80
133
 
81
134
  # Global config instance
@@ -18,6 +18,7 @@ class URLConfig(BaseModel):
18
18
 
19
19
  # Scanner/Detection URLs
20
20
  scanner_url: str = Field(
21
+ default="https://cloud.unrealon.com/scanner",
21
22
  description="URL for browser detection and stealth testing"
22
23
  )
23
24
 
@@ -39,19 +40,19 @@ class URLConfig(BaseModel):
39
40
 
40
41
  if environment == Environment.PRODUCTION:
41
42
  return cls(
42
- scanner_url="https://cloud.unrealon.com/scanner",
43
+ # scanner_url="https://cloud.unrealon.com/scanner",
43
44
  cloud_base_url="https://cloud.unrealon.com",
44
45
  api_base_url="https://api.unrealon.com"
45
46
  )
46
- elif environment == Environment.TESTING:
47
- return cls(
48
- scanner_url="https://staging.unrealon.com/scanner",
49
- cloud_base_url="https://staging.unrealon.com",
50
- api_base_url="https://api-staging.unrealon.com"
51
- )
47
+ # elif environment == Environment.TESTING:
48
+ # return cls(
49
+ # scanner_url="https://staging.unrealon.com/scanner",
50
+ # cloud_base_url="https://staging.unrealon.com",
51
+ # api_base_url="https://api-staging.unrealon.com"
52
+ # )
52
53
  else: # Development
53
54
  return cls(
54
- scanner_url="http://localhost:3000/scanner",
55
+ # scanner_url="http://localhost:3000/scanner",
55
56
  cloud_base_url="http://localhost:3000",
56
57
  api_base_url="http://localhost:8000"
57
58
  )
@@ -53,6 +53,7 @@ class MessageType(str, Enum):
53
53
  LOG_BATCH = "log_batch" # Batch of log messages
54
54
 
55
55
  # System messages
56
+ WELCOME = "welcome" # Welcome message from server
56
57
  PING = "ping" # Ping message
57
58
  PONG = "pong" # Pong response
58
59
  ERROR = "error" # Error message
@@ -46,16 +46,6 @@ from .logging import (
46
46
  LogMetrics
47
47
  )
48
48
 
49
- from .config import (
50
- SystemConfig,
51
- HttpConfig,
52
- ProxyConfig,
53
- BrowserConfig,
54
- LoggingConfig,
55
- CacheConfig,
56
- ThreadConfig
57
- )
58
-
59
49
  __all__ = [
60
50
  # Base models
61
51
  "UnrealOnBaseModel",
@@ -86,13 +76,4 @@ __all__ = [
86
76
  "LogEntry",
87
77
  "LogQuery",
88
78
  "LogMetrics",
89
-
90
- # Configuration models
91
- "SystemConfig",
92
- "HttpConfig",
93
- "ProxyConfig",
94
- "BrowserConfig",
95
- "LoggingConfig",
96
- "CacheConfig",
97
- "ThreadConfig",
98
79
  ]
@@ -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,137 @@
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
+
86
+ class DriverRegisterBroadcast(WebSocketMessage):
87
+ """Driver registration broadcast message (Server → Monitoring Clients)."""
88
+
89
+ model_config = ConfigDict(
90
+ validate_assignment=True,
91
+ extra="forbid"
92
+ )
93
+
94
+ type: MessageType = Field(
95
+ default=MessageType.DRIVER_REGISTER,
96
+ frozen=True
97
+ )
98
+
99
+ data: DriverBroadcastData = Field(
100
+ description="Driver registration broadcast data"
101
+ )
102
+
103
+
104
+ class DriverHeartbeatBroadcast(WebSocketMessage):
105
+ """Driver heartbeat broadcast message (Server → Monitoring Clients)."""
106
+
107
+ model_config = ConfigDict(
108
+ validate_assignment=True,
109
+ extra="forbid"
110
+ )
111
+
112
+ type: MessageType = Field(
113
+ default=MessageType.DRIVER_HEARTBEAT,
114
+ frozen=True
115
+ )
116
+
117
+ data: DriverBroadcastData = Field(
118
+ description="Driver heartbeat broadcast data"
119
+ )
120
+
121
+
122
+ class DriverDisconnectBroadcast(WebSocketMessage):
123
+ """Driver disconnect broadcast message (Server → Monitoring Clients)."""
124
+
125
+ model_config = ConfigDict(
126
+ validate_assignment=True,
127
+ extra="forbid"
128
+ )
129
+
130
+ type: MessageType = Field(
131
+ default=MessageType.DRIVER_DISCONNECT,
132
+ frozen=True
133
+ )
134
+
135
+ data: DriverBroadcastData = Field(
136
+ description="Driver disconnect broadcast data"
137
+ )
@@ -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
- # Validate task data
143
- task_data = TaskAssignmentData.model_validate(message.data)
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)
@@ -9,7 +9,15 @@ from typing import Optional, Callable, List
9
9
  from collections import deque
10
10
 
11
11
  import websockets
12
- from websockets.asyncio.client import ClientConnection
12
+ try:
13
+ from websockets.asyncio.client import ClientConnection
14
+ except ImportError:
15
+ # Fallback for older websockets versions
16
+ try:
17
+ from websockets.client import WebSocketClientProtocol as ClientConnection
18
+ except ImportError:
19
+ # Ultimate fallback
20
+ ClientConnection = None
13
21
 
14
22
  from unrealon_core.models.websocket import (
15
23
  DriverRegistrationMessage,
@@ -32,9 +40,11 @@ class WebSocketClient:
32
40
  - Clean error handling
33
41
  """
34
42
 
35
- def __init__(self, websocket_url: str, driver_id: str):
43
+ def __init__(self, websocket_url: str, driver_id: str, custom_logger=None):
36
44
  self.websocket_url = websocket_url
37
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
38
48
  self.websocket: Optional[ClientConnection] = None
39
49
  self.connected = False
40
50
  self.running = False
@@ -86,20 +96,20 @@ class WebSocketClient:
86
96
  self.websocket = None
87
97
 
88
98
  self.connected = False
89
- logger.info("WebSocket client stopped")
99
+ self._logger.info("WebSocket client stopped")
90
100
 
91
101
  async def _establish_connection(self) -> bool:
92
102
  """Establish WebSocket connection."""
93
103
  try:
94
- logger.info(f"Connecting to WebSocket: {self.websocket_url}")
104
+ self._logger.info(f"Connecting to WebSocket: {self.websocket_url}")
95
105
  self.websocket = await websockets.connect(self.websocket_url)
96
106
  self.connected = True
97
107
  self.reconnect_attempts = 0
98
108
  self.reconnect_delay = 1.0
99
- logger.info("WebSocket connected successfully")
109
+ self._logger.info("WebSocket connected successfully")
100
110
  return True
101
111
  except Exception as e:
102
- logger.error(f"WebSocket connection failed: {e}")
112
+ self._logger.error(f"WebSocket connection failed: {e}")
103
113
  self.connected = False
104
114
  return False
105
115
 
@@ -107,10 +117,10 @@ class WebSocketClient:
107
117
  """Monitor connection and handle reconnection."""
108
118
  while self.running:
109
119
  if not self.connected and self.running:
110
- logger.info(f"Attempting reconnection (attempt {self.reconnect_attempts + 1})")
120
+ self._logger.info(f"Attempting reconnection (attempt {self.reconnect_attempts + 1})")
111
121
 
112
122
  if await self._establish_connection():
113
- logger.info("Reconnection successful")
123
+ self._logger.info("Reconnection successful")
114
124
  else:
115
125
  self.reconnect_attempts += 1
116
126
  # Exponential backoff
@@ -128,13 +138,16 @@ class WebSocketClient:
128
138
  if self.connected and self.websocket and self.message_queue:
129
139
  try:
130
140
  message = self.message_queue.popleft()
141
+ self._logger.info(f"📤 Sending WebSocket message: {message[:200]}...") # Log first 200 chars
131
142
  await self.websocket.send(message)
143
+ self._logger.info(f"✅ Message sent successfully")
132
144
  except (websockets.exceptions.ConnectionClosed, ConnectionResetError):
133
145
  self.connected = False
134
146
  # Put message back in queue
135
147
  self.message_queue.appendleft(message)
148
+ self._logger.warning("🔌 Connection lost, message queued for retry")
136
149
  except Exception as e:
137
- logger.error(f"Error sending message: {e}")
150
+ self._logger.error(f"Error sending message: {e}")
138
151
  else:
139
152
  await asyncio.sleep(0.1)
140
153
 
@@ -155,9 +168,9 @@ class WebSocketClient:
155
168
 
156
169
  except (websockets.exceptions.ConnectionClosed, ConnectionResetError):
157
170
  self.connected = False
158
- logger.warning("WebSocket connection lost")
171
+ self._logger.warning("WebSocket connection lost")
159
172
  except Exception as e:
160
- logger.error(f"Error receiving message: {e}")
173
+ self._logger.error(f"Error receiving message: {e}")
161
174
  else:
162
175
  await asyncio.sleep(0.1)
163
176
 
@@ -189,9 +202,9 @@ class WebSocketClient:
189
202
  # Queue for sending
190
203
  self.send(registration_message)
191
204
 
192
- logger.info(f"Driver registration queued: {self.driver_id}")
205
+ self._logger.info(f"Driver registration queued: {self.driver_id}")
193
206
  return True
194
207
 
195
208
  except Exception as e:
196
- logger.error(f"Driver registration failed: {e}")
209
+ self._logger.error(f"Driver registration failed: {e}")
197
210
  return False
@@ -7,6 +7,12 @@ from enum import Enum
7
7
  from typing import Optional
8
8
  from pydantic import BaseModel, Field, computed_field
9
9
 
10
+ try:
11
+ from unrealon_core.config.environment import get_environment_config
12
+ UNREALON_CORE_AVAILABLE = True
13
+ except ImportError:
14
+ UNREALON_CORE_AVAILABLE = False
15
+
10
16
 
11
17
  class DriverMode(str, Enum):
12
18
  """Driver operation modes."""
@@ -36,9 +42,9 @@ class DriverConfig(BaseModel):
36
42
 
37
43
  Priority:
38
44
  1. Explicit websocket_url field
39
- 2. Environment variable UNREALON_WEBSOCKET_URL
40
- 3. Environment variable UNREALON_WS_URL
41
- 4. Default localhost for development
45
+ 2. Environment variables (UNREALON_WEBSOCKET_URL, UNREALON_WS_URL, WS_URL)
46
+ 3. UnrealOn core environment config (if available)
47
+ 4. No default - return None if nothing configured
42
48
  """
43
49
  # 1. Explicit override
44
50
  if self.websocket_url:
@@ -53,7 +59,15 @@ class DriverConfig(BaseModel):
53
59
  if env_url:
54
60
  return env_url
55
61
 
56
- # 3. No default - return None if nothing is configured
62
+ # 3. Try unrealon_core environment config
63
+ if UNREALON_CORE_AVAILABLE:
64
+ try:
65
+ env_config = get_environment_config()
66
+ return env_config.websocket_url
67
+ except Exception:
68
+ pass # Fallback gracefully if core config fails
69
+
70
+ # 4. No default - return None if nothing is configured
57
71
  return None
58
72
 
59
73
  # Logging
@@ -83,3 +97,79 @@ class DriverConfig(BaseModel):
83
97
  batch_size: int = Field(default=10, description="Batch processing size")
84
98
 
85
99
  model_config = {"extra": "forbid"}
100
+
101
+ @classmethod
102
+ def for_development(cls, name: str, **kwargs) -> "DriverConfig":
103
+ """
104
+ Create development configuration with sensible defaults.
105
+
106
+ Args:
107
+ name: Driver name
108
+ **kwargs: Additional configuration overrides
109
+ """
110
+ defaults = {
111
+ "name": name,
112
+ "mode": DriverMode.STANDALONE,
113
+ "log_level": "DEBUG",
114
+ "browser_headless": False,
115
+ "proxy_enabled": False,
116
+ "cache_enabled": True,
117
+ "max_workers": 2,
118
+ }
119
+ defaults.update(kwargs)
120
+ return cls(**defaults)
121
+
122
+ @classmethod
123
+ def for_production(cls, name: str, **kwargs) -> "DriverConfig":
124
+ """
125
+ Create production configuration with performance and reliability defaults.
126
+
127
+ Args:
128
+ name: Driver name
129
+ **kwargs: Additional configuration overrides
130
+ """
131
+ defaults = {
132
+ "name": name,
133
+ "mode": DriverMode.DAEMON,
134
+ "log_level": "INFO",
135
+ "browser_headless": True,
136
+ "proxy_enabled": True,
137
+ "cache_enabled": True,
138
+ "max_workers": 4,
139
+ "max_retries": 5,
140
+ "http_timeout": 60,
141
+ "browser_timeout": 60,
142
+ }
143
+ defaults.update(kwargs)
144
+ return cls(**defaults)
145
+
146
+ @classmethod
147
+ def auto_detect(cls, name: str, **kwargs) -> "DriverConfig":
148
+ """
149
+ Auto-detect environment and create appropriate configuration.
150
+
151
+ Uses UNREALON_ENV environment variable or unrealon_core config to determine environment.
152
+
153
+ Args:
154
+ name: Driver name
155
+ **kwargs: Additional configuration overrides
156
+ """
157
+ # Try to detect environment
158
+ env_name = os.getenv("UNREALON_ENV", "development").lower()
159
+
160
+ # Try unrealon_core if available
161
+ if UNREALON_CORE_AVAILABLE:
162
+ try:
163
+ env_config = get_environment_config()
164
+ if env_config.is_production:
165
+ return cls.for_production(name, **kwargs)
166
+ elif env_config.is_development:
167
+ return cls.for_development(name, **kwargs)
168
+ except Exception:
169
+ pass # Fallback to env variable
170
+
171
+ # Fallback to environment variable
172
+ if env_name in ("prod", "production"):
173
+ return cls.for_production(name, **kwargs)
174
+ else:
175
+ return cls.for_development(name, **kwargs)
@@ -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
 
@@ -1,47 +0,0 @@
1
- """
2
- Config models - Phase 2 update.
3
-
4
- Import from strictly typed websocket models to avoid duplication.
5
- Following critical requirements - no raw Dict[str, Any].
6
- """
7
-
8
- # Import strictly typed models from websocket package
9
- from .websocket.config import (
10
- DriverConfiguration,
11
- LoggingConfiguration,
12
- TaskConfiguration,
13
- ProxyConfiguration
14
- )
15
- from .base import ConfigBaseModel
16
-
17
- # System config that doesn't exist in websocket models yet
18
- class SystemConfig(ConfigBaseModel):
19
- """System-wide configuration."""
20
-
21
- redis_url: str = "redis://localhost:6379/0"
22
- websocket_url: str = "ws://localhost:8000/ws"
23
- max_workers: int = 10
24
- debug: bool = False
25
-
26
- # Legacy compatibility - map to new typed models
27
- HttpConfig = TaskConfiguration # HTTP settings are part of task config
28
- ProxyConfig = ProxyConfiguration
29
- LoggingConfig = LoggingConfiguration
30
- BrowserConfig = TaskConfiguration # Browser settings are part of task config
31
- CacheConfig = SystemConfig # Cache settings are system-wide
32
- ThreadConfig = TaskConfiguration # Thread settings are part of task config
33
-
34
- __all__ = [
35
- 'DriverConfiguration',
36
- 'LoggingConfiguration',
37
- 'TaskConfiguration',
38
- 'ProxyConfiguration',
39
- 'SystemConfig',
40
- # Legacy names
41
- 'HttpConfig',
42
- 'ProxyConfig',
43
- 'LoggingConfig',
44
- 'BrowserConfig',
45
- 'CacheConfig',
46
- 'ThreadConfig'
47
- ]