fleet-framework 0.1.1__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/PKG-INFO +5 -2
  2. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/browser.py +66 -3
  3. fleet_framework-0.1.2/fleet_browser/cloak.py +120 -0
  4. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/fingerprint.py +6 -1
  5. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_framework.egg-info/PKG-INFO +5 -2
  6. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_framework.egg-info/SOURCES.txt +1 -0
  7. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_framework.egg-info/requires.txt +5 -1
  8. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/pyproject.toml +6 -2
  9. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/LICENSE +0 -0
  10. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/README.md +0 -0
  11. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/__init__.py +0 -0
  12. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/cli.py +0 -0
  13. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/__init__.py +0 -0
  14. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/automation.py +0 -0
  15. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/backend.py +0 -0
  16. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/config.py +0 -0
  17. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/context.py +0 -0
  18. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/contract.py +0 -0
  19. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/country_presets.py +0 -0
  20. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/events.py +0 -0
  21. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/local_runner.py +0 -0
  22. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/logging.py +0 -0
  23. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/memory_backend.py +0 -0
  24. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/metrics.py +0 -0
  25. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/otel.py +0 -0
  26. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/primitives.py +0 -0
  27. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/protocol.py +0 -0
  28. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/proxy.py +0 -0
  29. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/reconcile.py +0 -0
  30. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/sqlite_backend.py +0 -0
  31. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/core/store.py +0 -0
  32. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/__init__.py +0 -0
  33. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/api.py +0 -0
  34. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/app.py +0 -0
  35. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/auth.py +0 -0
  36. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/broadcaster.py +0 -0
  37. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/dashboard/__init__.py +0 -0
  38. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/dashboard/router.py +0 -0
  39. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/dashboard/static/style.css +0 -0
  40. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/dashboard/templates/index.html +0 -0
  41. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/metrics_route.py +0 -0
  42. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/ratelimit.py +0 -0
  43. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/master/ws_router.py +0 -0
  44. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/worker/__init__.py +0 -0
  45. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/worker/agent.py +0 -0
  46. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/worker/reconcile_loop.py +0 -0
  47. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/worker/slot_runner.py +0 -0
  48. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet/worker/ws_client.py +0 -0
  49. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/__init__.py +0 -0
  50. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/cert.py +0 -0
  51. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/humanizer.py +0 -0
  52. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/pool.py +0 -0
  53. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/proxy_extension.py +0 -0
  54. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/solver.py +0 -0
  55. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_browser/stealth.py +0 -0
  56. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_cloudflare/__init__.py +0 -0
  57. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_cloudflare/bypasser.py +0 -0
  58. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_cloudflare/harvest.py +0 -0
  59. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_cloudflare/replay.py +0 -0
  60. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_cloudflare/solver.py +0 -0
  61. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_content/__init__.py +0 -0
  62. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_content/automation.py +0 -0
  63. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_content/contracts.py +0 -0
  64. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_detect/__init__.py +0 -0
  65. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_detect/contracts.py +0 -0
  66. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_detect/detect.py +0 -0
  67. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_framework.egg-info/dependency_links.txt +0 -0
  68. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_framework.egg-info/entry_points.txt +0 -0
  69. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_framework.egg-info/top_level.txt +0 -0
  70. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_headers/__init__.py +0 -0
  71. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_headers/profiles.py +0 -0
  72. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_jobs/__init__.py +0 -0
  73. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_jobs/automation.py +0 -0
  74. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_jobs/contracts.py +0 -0
  75. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_marketplace/__init__.py +0 -0
  76. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_marketplace/automation.py +0 -0
  77. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_marketplace/contracts.py +0 -0
  78. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_news/__init__.py +0 -0
  79. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_news/automation.py +0 -0
  80. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_news/contracts.py +0 -0
  81. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_place/__init__.py +0 -0
  82. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_place/automation.py +0 -0
  83. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_place/contracts.py +0 -0
  84. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_provider_dataimpulse/__init__.py +0 -0
  85. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_provider_evomi/__init__.py +0 -0
  86. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_serp/__init__.py +0 -0
  87. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_serp/automation.py +0 -0
  88. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_serp/contracts.py +0 -0
  89. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_social/__init__.py +0 -0
  90. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_social/automation.py +0 -0
  91. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/fleet_social/contracts.py +0 -0
  92. {fleet_framework-0.1.1 → fleet_framework-0.1.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-framework
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: generic distributed-automation framework — master/worker, browser pool, anti-bot helpers, and abstract automation contracts (SERP, content, news, place, marketplace, jobs, social)
5
5
  Author: Sarper Avci
6
6
  License: MIT
@@ -23,6 +23,9 @@ Requires-Dist: DrissionPage>=4.1.0; extra == "browser"
23
23
  Requires-Dist: cryptography>=42.0.0; extra == "browser"
24
24
  Provides-Extra: cloudflare
25
25
  Requires-Dist: fleet-framework[browser]; extra == "cloudflare"
26
+ Provides-Extra: cloak
27
+ Requires-Dist: fleet-framework[browser]; extra == "cloak"
28
+ Requires-Dist: cloakbrowser>=0.3; extra == "cloak"
26
29
  Provides-Extra: otel
27
30
  Requires-Dist: opentelemetry-api>=1.27.0; extra == "otel"
28
31
  Requires-Dist: opentelemetry-sdk>=1.27.0; extra == "otel"
@@ -31,7 +34,7 @@ Provides-Extra: test
31
34
  Requires-Dist: pytest>=8.0; extra == "test"
32
35
  Requires-Dist: pytest-asyncio>=0.23; extra == "test"
33
36
  Provides-Extra: all
34
- Requires-Dist: fleet-framework[browser,cloudflare,otel]; extra == "all"
37
+ Requires-Dist: fleet-framework[browser,cloak,cloudflare,otel]; extra == "all"
35
38
  Dynamic: license-file
36
39
 
37
40
  # Fleet
@@ -13,6 +13,12 @@ from typing import Optional
13
13
  import psutil
14
14
  from DrissionPage import ChromiumOptions, ChromiumPage
15
15
 
16
+ from fleet_browser.cloak import (
17
+ CLOAK_IGNORE_DEFAULT_ARGS,
18
+ cloak_stealth_args,
19
+ ensure_cloak_binary,
20
+ resolve_engine,
21
+ )
16
22
  from fleet_browser.proxy_extension import build_proxy_auth_extension, parse_proxy_url
17
23
  from fleet_browser.stealth import Stealth
18
24
 
@@ -120,6 +126,39 @@ class BrowserConfig:
120
126
 
121
127
  extra_args: tuple[str, ...] = ()
122
128
 
129
+ engine: str = "auto"
130
+ """Which Chromium build to launch. `"auto"` picks `"cloak"` when the
131
+ cloakbrowser package is installed, else falls back to `"chrome"`.
132
+ Set explicitly to override:
133
+ - `"chrome"`: use the system Chromium / Brave / Thorium auto-detect path
134
+ - `"cloak"`: use the CloakBrowser patched binary (downloads on first
135
+ use, raises if `cloakbrowser` isn't installed)
136
+ Cloak applies source-level canvas/WebGL/audio/font/WebRTC patches that
137
+ JS-level stealth can't reach. Stack FingerprintStealth on top to add
138
+ per-launch UA/version diversity from the uaforge corpus."""
139
+
140
+ cloak_cache_dir: Optional[str] = None
141
+ """Override the cloak binary cache dir (default ~/.cloakbrowser/)."""
142
+
143
+ cloak_fingerprint_seed: Optional[int] = None
144
+ """Force a specific cloak --fingerprint=N seed. Default: random per
145
+ launch. Pin a seed for reproducible tests."""
146
+
147
+ cloak_platform: str = "windows"
148
+ """`--fingerprint-platform` flag for cloak's binary. Must match the
149
+ OS family FingerprintStealth's UA claims (uaforge default is Windows).
150
+ Set 'macos' if you switch uaforge to a Mac corpus."""
151
+
152
+ cloak_timezone: Optional[str] = None
153
+ """IANA timezone for cloak's `--fingerprint-timezone` flag. Set when
154
+ using residential proxies so the spoofed timezone matches the egress
155
+ geo (otherwise CF flags the mismatch). Falls back to system tz."""
156
+
157
+ cloak_webrtc_ip: Optional[str] = None
158
+ """Public IP cloak should advertise via WebRTC. Set to the proxy's exit
159
+ IP when using residential — otherwise WebRTC leaks your real LAN IP
160
+ and CF correlates the mismatch."""
161
+
123
162
 
124
163
  class ChromiumWorker:
125
164
 
@@ -133,9 +172,16 @@ class ChromiumWorker:
133
172
  if self.page is not None:
134
173
  return self.page
135
174
 
136
- binary = self.config.browser_binary or _find_browser_binary(
137
- prefer=self.config.prefer_browser,
138
- )
175
+ engine = resolve_engine(self.config.engine)
176
+ if engine == "cloak":
177
+ # Caller may still pin browser_binary explicitly — honor it.
178
+ binary = self.config.browser_binary or ensure_cloak_binary(
179
+ self.config.cloak_cache_dir
180
+ )
181
+ else:
182
+ binary = self.config.browser_binary or _find_browser_binary(
183
+ prefer=self.config.prefer_browser,
184
+ )
139
185
 
140
186
  self._user_data_dir = Path(tempfile.mkdtemp(prefix="chromium-worker-"))
141
187
  self._owns_user_data_dir = True
@@ -147,6 +193,23 @@ class ChromiumWorker:
147
193
  opts.set_user_data_path(str(self._user_data_dir))
148
194
  opts.set_argument(f"--window-size={self.config.window_size[0]},{self.config.window_size[1]}")
149
195
 
196
+ if engine == "cloak":
197
+ for arg in cloak_stealth_args(
198
+ platform=self.config.cloak_platform,
199
+ timezone=self.config.cloak_timezone,
200
+ webrtc_ip=self.config.cloak_webrtc_ip,
201
+ seed=self.config.cloak_fingerprint_seed,
202
+ ):
203
+ opts.set_argument(arg)
204
+ # Suppress Chromium defaults that leak automation signals.
205
+ # DrissionPage doesn't expose ignore_default_args; pass as
206
+ # --disable-features-replacement via plain args. The cloak
207
+ # binary recognises --no-enable-automation as an inversion.
208
+ for kill in CLOAK_IGNORE_DEFAULT_ARGS:
209
+ # Chromium accepts --disable-foo as the inverse of --enable-foo.
210
+ inv = kill.replace("--enable-", "--disable-", 1)
211
+ opts.set_argument(inv)
212
+
150
213
  # HttpsUpgrades is off so self-signed HTTPS (TokenServer) isn't rewritten.
151
214
  # Brave's ad/tracker/sync features both pollute the fingerprint and
152
215
  # sometimes break Turnstile's iframe; disable them when running Brave.
@@ -0,0 +1,120 @@
1
+ """Cloak engine integration — uses the CloakBrowser patched Chromium binary.
2
+
3
+ CloakBrowser is a separately-licensed binary (free for own-business use,
4
+ OEM license required for browser-as-a-service distribution). See:
5
+ https://github.com/CloakHQ/CloakBrowser
6
+
7
+ The wrapper Python package is MIT-licensed and pulled in via the optional
8
+ extra: `pip install fleet-framework[cloak]`. The binary is downloaded on
9
+ first use to ~/.cloakbrowser/ (override with CLOAKBROWSER_CACHE_DIR).
10
+
11
+ Combining cloak (source-level canvas/WebGL/audio/font/WebRTC patches) with
12
+ FingerprintStealth (CDP-level UA + Sec-CH-UA + navigator overrides) gives:
13
+ - Deep, JS-undetectable spoofing of low-level signals (cloak)
14
+ - Per-launch diversity of UA versions from the uaforge corpus (FingerprintStealth)
15
+
16
+ That diversity matters: cloak's binary patches use the latest Chrome only,
17
+ so without the CDP layer every harvest looks like the same Chrome version.
18
+ With CDP override on top, each launch picks a different version from uaforge
19
+ while keeping the renderer-level fingerprint coherent.
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import logging
24
+ import os
25
+ import random
26
+ from pathlib import Path
27
+ from typing import Optional
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ _CLOAK_AVAILABLE: Optional[bool] = None
33
+
34
+
35
+ def cloak_available() -> bool:
36
+ """Return True if the cloakbrowser wrapper package is importable.
37
+
38
+ The binary may still need to be downloaded — that's `ensure_cloak_binary`'s
39
+ job. This is just the cheap import probe.
40
+ """
41
+ global _CLOAK_AVAILABLE
42
+ if _CLOAK_AVAILABLE is None:
43
+ try:
44
+ import cloakbrowser # noqa: F401
45
+ _CLOAK_AVAILABLE = True
46
+ except ImportError:
47
+ _CLOAK_AVAILABLE = False
48
+ return _CLOAK_AVAILABLE
49
+
50
+
51
+ def resolve_engine(name: str) -> str:
52
+ """Resolve `engine="auto"` to `"cloak"` if available, else `"chrome"`."""
53
+ if name != "auto":
54
+ return name
55
+ return "cloak" if cloak_available() else "chrome"
56
+
57
+
58
+ def ensure_cloak_binary(cache_dir: Optional[str] = None) -> str:
59
+ """Return path to the patched Chromium binary; download if missing.
60
+
61
+ Delegates to cloakbrowser.download.ensure_binary. ~250-400 MB download
62
+ on first use; cached at ~/.cloakbrowser/ (or `cache_dir`) thereafter.
63
+ Cloakbrowser checks for updates hourly when launched.
64
+ """
65
+ if not cloak_available():
66
+ raise RuntimeError(
67
+ "engine='cloak' requires cloakbrowser. "
68
+ "Install with: pip install fleet-framework[cloak]"
69
+ )
70
+ if cache_dir:
71
+ os.environ.setdefault("CLOAKBROWSER_CACHE_DIR", str(Path(cache_dir).expanduser()))
72
+ from cloakbrowser.download import ensure_binary
73
+ path = ensure_binary()
74
+ return str(path)
75
+
76
+
77
+ def cloak_stealth_args(
78
+ *,
79
+ platform: str = "windows",
80
+ timezone: Optional[str] = None,
81
+ webrtc_ip: Optional[str] = None,
82
+ seed: Optional[int] = None,
83
+ ) -> tuple[str, ...]:
84
+ """Return Chromium command-line flags that activate cloak's source patches.
85
+
86
+ The `seed` drives canvas/WebGL/audio noise variation per-launch. Pass a
87
+ stable seed if you need reproducibility (e.g. testing). `platform` should
88
+ match what FingerprintStealth's UA claims — keep them aligned (default
89
+ 'windows' matches uaforge's Windows corpus).
90
+ """
91
+ s = seed if seed is not None else random.randint(10000, 99999)
92
+ args = [
93
+ f"--fingerprint={s}",
94
+ f"--fingerprint-platform={platform}",
95
+ ]
96
+ if timezone:
97
+ args.append(f"--fingerprint-timezone={timezone}")
98
+ if webrtc_ip:
99
+ args.append(f"--fingerprint-webrtc-ip={webrtc_ip}")
100
+ return tuple(args)
101
+
102
+
103
+ CLOAK_IGNORE_DEFAULT_ARGS: tuple[str, ...] = (
104
+ "--enable-automation",
105
+ "--enable-unsafe-swiftshader",
106
+ )
107
+ """Default args Playwright/DrissionPage pass that leak automation signals.
108
+
109
+ `--enable-automation` exposes `navigator.webdriver=true`. `--enable-unsafe-
110
+ swiftshader` forces SwiftShader's distinctive WebGL renderer string. We pass
111
+ these to Chromium's launch options so DrissionPage stops setting them."""
112
+
113
+
114
+ __all__ = [
115
+ "CLOAK_IGNORE_DEFAULT_ARGS",
116
+ "cloak_available",
117
+ "cloak_stealth_args",
118
+ "ensure_cloak_binary",
119
+ "resolve_engine",
120
+ ]
@@ -180,7 +180,12 @@ class FingerprintFactory:
180
180
  "pip install git+https://github.com/sarperavci/uaforge.git"
181
181
  )
182
182
  if allowed_os is None:
183
- allowed_os = (_detect_host_os(),)
183
+ # Default to Windows regardless of host. The host's actual OS
184
+ # is irrelevant — what matters is which UA + client-hint corpus
185
+ # the fleet's fingerprints are drawn from. Windows is the highest-
186
+ # entropy population (~70% of real browsing traffic) and matches
187
+ # the cloak engine's `--fingerprint-platform=windows` default.
188
+ allowed_os = ("windows",)
184
189
  self._gen = UserAgentGenerator(seed=seed)
185
190
  self._rng = random.Random(seed)
186
191
  self._min_chromium = min_chromium_version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-framework
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: generic distributed-automation framework — master/worker, browser pool, anti-bot helpers, and abstract automation contracts (SERP, content, news, place, marketplace, jobs, social)
5
5
  Author: Sarper Avci
6
6
  License: MIT
@@ -23,6 +23,9 @@ Requires-Dist: DrissionPage>=4.1.0; extra == "browser"
23
23
  Requires-Dist: cryptography>=42.0.0; extra == "browser"
24
24
  Provides-Extra: cloudflare
25
25
  Requires-Dist: fleet-framework[browser]; extra == "cloudflare"
26
+ Provides-Extra: cloak
27
+ Requires-Dist: fleet-framework[browser]; extra == "cloak"
28
+ Requires-Dist: cloakbrowser>=0.3; extra == "cloak"
26
29
  Provides-Extra: otel
27
30
  Requires-Dist: opentelemetry-api>=1.27.0; extra == "otel"
28
31
  Requires-Dist: opentelemetry-sdk>=1.27.0; extra == "otel"
@@ -31,7 +34,7 @@ Provides-Extra: test
31
34
  Requires-Dist: pytest>=8.0; extra == "test"
32
35
  Requires-Dist: pytest-asyncio>=0.23; extra == "test"
33
36
  Provides-Extra: all
34
- Requires-Dist: fleet-framework[browser,cloudflare,otel]; extra == "all"
37
+ Requires-Dist: fleet-framework[browser,cloak,cloudflare,otel]; extra == "all"
35
38
  Dynamic: license-file
36
39
 
37
40
  # Fleet
@@ -42,6 +42,7 @@ fleet/worker/ws_client.py
42
42
  fleet_browser/__init__.py
43
43
  fleet_browser/browser.py
44
44
  fleet_browser/cert.py
45
+ fleet_browser/cloak.py
45
46
  fleet_browser/fingerprint.py
46
47
  fleet_browser/humanizer.py
47
48
  fleet_browser/pool.py
@@ -9,12 +9,16 @@ psutil>=5.9.0
9
9
  click>=8.1.0
10
10
 
11
11
  [all]
12
- fleet-framework[browser,cloudflare,otel]
12
+ fleet-framework[browser,cloak,cloudflare,otel]
13
13
 
14
14
  [browser]
15
15
  DrissionPage>=4.1.0
16
16
  cryptography>=42.0.0
17
17
 
18
+ [cloak]
19
+ fleet-framework[browser]
20
+ cloakbrowser>=0.3
21
+
18
22
  [cloudflare]
19
23
  fleet-framework[browser]
20
24
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fleet-framework"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "generic distributed-automation framework — master/worker, browser pool, anti-bot helpers, and abstract automation contracts (SERP, content, news, place, marketplace, jobs, social)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -30,6 +30,10 @@ browser = [
30
30
  cloudflare = [
31
31
  "fleet-framework[browser]",
32
32
  ]
33
+ cloak = [
34
+ "fleet-framework[browser]",
35
+ "cloakbrowser>=0.3",
36
+ ]
33
37
  otel = [
34
38
  "opentelemetry-api>=1.27.0",
35
39
  "opentelemetry-sdk>=1.27.0",
@@ -40,7 +44,7 @@ test = [
40
44
  "pytest-asyncio>=0.23",
41
45
  ]
42
46
  all = [
43
- "fleet-framework[browser,cloudflare,otel]",
47
+ "fleet-framework[browser,cloudflare,cloak,otel]",
44
48
  ]
45
49
 
46
50
  [project.scripts]
File without changes