webpilot-engine 2.0.3__tar.gz → 2.0.4__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.
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/PKG-INFO +8 -3
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/adapters/live_session_manager.py +9 -6
- webpilot_engine-2.0.4/common/__init__.py +17 -0
- webpilot_engine-2.0.4/common/cookies.py +48 -0
- webpilot_engine-2.0.4/common/logging.py +52 -0
- webpilot_engine-2.0.4/common/retry.py +31 -0
- webpilot_engine-2.0.4/common/text.py +19 -0
- webpilot_engine-2.0.4/config/device_profile.example.json +17 -0
- webpilot_engine-2.0.4/config/device_profile.json +17 -0
- webpilot_engine-2.0.4/config/settings.example.json +12 -0
- webpilot_engine-2.0.4/config/settings.json +12 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/pyproject.toml +14 -4
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/supervisor/shell.py +1 -1
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/webpilot_engine.egg-info/PKG-INFO +8 -3
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/webpilot_engine.egg-info/SOURCES.txt +9 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/webpilot_engine.egg-info/requires.txt +1 -1
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/webpilot_engine.egg-info/top_level.txt +1 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/README.md +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/adapters/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/adapters/base.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/adapters/browser_adapter.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/adapters/dom_scripts.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/adapters/envelope_builder.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/adapters/upload_adapter.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/builder.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/cli.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/config/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/config/settings.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/constants/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/constants/contracts.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/constants/selectors.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/constants/timeouts.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/core/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/core/exceptions.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/core/models.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/engine.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/exceptions.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/mcp_server.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/models.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/orchestration/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/orchestration/context.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/orchestration/flow_orchestrator.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/orchestration/session_coordinator.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/services/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/services/auth_navigation_service.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/services/field_interaction_service.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/services/form_filler_service.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/services/inspection_formatter_service.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/services/inspection_service.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/services/reactive_interaction_service.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/setup.cfg +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/supervisor/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/supervisor/client.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/supervisor/contracts.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/supervisor/master_daemon.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/supervisor/worker_process.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_config_and_builder.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_contracts.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_engine_facade.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_live_session.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_mcp_server.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_orchestration.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_redaction.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_services.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/tests/test_supervisor.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/validators/__init__.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/validators/form_validator.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/validators/payload_validator.py +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/webpilot_engine.egg-info/dependency_links.txt +0 -0
- {webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/webpilot_engine.egg-info/entry_points.txt +0 -0
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: webpilot-engine
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: WebPilot: Enterprise Autonomous Browser Engine, Universal Form Inspector & AI Agent Web Runtime
|
|
5
5
|
Author: Abdulkarim Salih, WebPilot Core Team
|
|
6
6
|
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/AbdulkarimSSS/webpilot
|
|
8
|
+
Project-URL: Documentation, https://github.com/AbdulkarimSSS/webpilot#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/AbdulkarimSSS/webpilot.git
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/AbdulkarimSSS/webpilot/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/AbdulkarimSSS/webpilot/blob/master/CHANGELOG.md
|
|
7
12
|
Keywords: webpilot,browser-runtime,ai-agent,web-automation,playwright,form-filler,ats-automation,sap-successfactors,workday,browser-supervisor,process-isolation
|
|
8
|
-
Classifier: Development Status ::
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
14
|
Classifier: Intended Audience :: Developers
|
|
10
15
|
Classifier: Topic :: Software Development :: Testing
|
|
11
16
|
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
@@ -28,7 +33,7 @@ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
|
28
33
|
Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
|
|
29
34
|
Requires-Dist: Faker>=24.0.0; extra == "dev"
|
|
30
35
|
Provides-Extra: mcp
|
|
31
|
-
Requires-Dist: mcp
|
|
36
|
+
Requires-Dist: mcp<2,>=1.0.0; extra == "mcp"
|
|
32
37
|
|
|
33
38
|
# WebPilot: Autonomous Multi-Tier Browser Automation Engine & AI Agent Web Runtime
|
|
34
39
|
|
|
@@ -210,13 +210,16 @@ class LiveSessionManager:
|
|
|
210
210
|
time.sleep(0.2)
|
|
211
211
|
|
|
212
212
|
if not active:
|
|
213
|
-
if
|
|
213
|
+
if proc_pid:
|
|
214
214
|
try:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
215
|
+
if sys.platform == "win32":
|
|
216
|
+
subprocess.run(
|
|
217
|
+
["taskkill", "/F", "/T", "/PID", str(proc_pid)],
|
|
218
|
+
stdout=subprocess.DEVNULL,
|
|
219
|
+
stderr=subprocess.DEVNULL,
|
|
220
|
+
)
|
|
221
|
+
else:
|
|
222
|
+
os.kill(proc_pid, 9)
|
|
220
223
|
except Exception:
|
|
221
224
|
pass
|
|
222
225
|
raise RuntimeError(f"Chromium failed to open CDP port {port} within 5 seconds.")
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Common utilities package for universal web applier."""
|
|
2
|
+
|
|
3
|
+
from common.text import clean_label, truncate_text
|
|
4
|
+
from common.cookies import sanitize_cookies, load_and_sanitize_cookies, save_cookies
|
|
5
|
+
from common.retry import with_retry
|
|
6
|
+
from common.logging import redact_sensitive, log_event
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"clean_label",
|
|
10
|
+
"truncate_text",
|
|
11
|
+
"sanitize_cookies",
|
|
12
|
+
"load_and_sanitize_cookies",
|
|
13
|
+
"save_cookies",
|
|
14
|
+
"with_retry",
|
|
15
|
+
"redact_sensitive",
|
|
16
|
+
"log_event",
|
|
17
|
+
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Cookie sanitization and persistence helpers for Playwright."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
from core.exceptions import ValidationError
|
|
7
|
+
|
|
8
|
+
INVALID_COOKIE_KEYS = ("hostOnly", "session", "storeId", "id")
|
|
9
|
+
VALID_SAME_SITE_VALUES = ("Strict", "Lax", "None")
|
|
10
|
+
|
|
11
|
+
def sanitize_cookies(raw_cookies: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
12
|
+
"""Sanitizes raw cookie objects ensuring full Playwright compatibility."""
|
|
13
|
+
if not isinstance(raw_cookies, list):
|
|
14
|
+
raise ValidationError(f"Expected list of cookies, got {type(raw_cookies).__name__}")
|
|
15
|
+
|
|
16
|
+
sanitized: List[Dict[str, Any]] = []
|
|
17
|
+
for c in raw_cookies:
|
|
18
|
+
if not isinstance(c, dict):
|
|
19
|
+
continue
|
|
20
|
+
cookie = dict(c)
|
|
21
|
+
same_site = str(cookie.get("sameSite", "")).capitalize()
|
|
22
|
+
if same_site in VALID_SAME_SITE_VALUES:
|
|
23
|
+
cookie["sameSite"] = same_site
|
|
24
|
+
else:
|
|
25
|
+
cookie.pop("sameSite", None)
|
|
26
|
+
|
|
27
|
+
for key in INVALID_COOKIE_KEYS:
|
|
28
|
+
cookie.pop(key, None)
|
|
29
|
+
|
|
30
|
+
sanitized.append(cookie)
|
|
31
|
+
|
|
32
|
+
return sanitized
|
|
33
|
+
|
|
34
|
+
def load_and_sanitize_cookies(filepath: str) -> List[Dict[str, Any]]:
|
|
35
|
+
"""Loads a JSON cookie file from disk and returns sanitized cookie dictionaries."""
|
|
36
|
+
if not os.path.isfile(filepath):
|
|
37
|
+
raise FileNotFoundError(f"Cookie file not found: {filepath}")
|
|
38
|
+
|
|
39
|
+
with open(filepath, "r", encoding="utf-8") as f:
|
|
40
|
+
raw_cookies = json.load(f)
|
|
41
|
+
|
|
42
|
+
return sanitize_cookies(raw_cookies)
|
|
43
|
+
|
|
44
|
+
def save_cookies(filepath: str, cookies: List[Dict[str, Any]]) -> None:
|
|
45
|
+
"""Persists cookie objects to disk formatted cleanly."""
|
|
46
|
+
os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
|
|
47
|
+
with open(filepath, "w", encoding="utf-8") as f:
|
|
48
|
+
json.dump(cookies, f, indent=2, ensure_ascii=False)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Structured logging and sensitive data redaction utilities."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Any, Dict, List, Set, Union
|
|
5
|
+
|
|
6
|
+
SENSITIVE_KEY_PATTERNS: Set[str] = {
|
|
7
|
+
"password",
|
|
8
|
+
"secret",
|
|
9
|
+
"token",
|
|
10
|
+
"api_key",
|
|
11
|
+
"apikey",
|
|
12
|
+
"national_id",
|
|
13
|
+
"iqama",
|
|
14
|
+
"ssn",
|
|
15
|
+
"credentials",
|
|
16
|
+
"auth",
|
|
17
|
+
"cookie",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def redact_sensitive(data: Any) -> Any:
|
|
22
|
+
"""Recursively redacts sensitive keys and values from dictionaries, lists, or strings."""
|
|
23
|
+
if isinstance(data, dict):
|
|
24
|
+
redacted = {}
|
|
25
|
+
for k, v in data.items():
|
|
26
|
+
k_lower = str(k).lower().strip()
|
|
27
|
+
if any(p in k_lower for p in SENSITIVE_KEY_PATTERNS):
|
|
28
|
+
redacted[k] = "[REDACTED]"
|
|
29
|
+
else:
|
|
30
|
+
redacted[k] = redact_sensitive(v)
|
|
31
|
+
return redacted
|
|
32
|
+
|
|
33
|
+
if isinstance(data, list):
|
|
34
|
+
return [redact_sensitive(item) for item in data]
|
|
35
|
+
|
|
36
|
+
if isinstance(data, tuple):
|
|
37
|
+
return tuple(redact_sensitive(item) for item in data)
|
|
38
|
+
|
|
39
|
+
if isinstance(data, str):
|
|
40
|
+
# Redact patterns resembling 9-10 digit national IDs (excluding all-zeros placeholders)
|
|
41
|
+
masked = re.sub(r"\b(?!0{9,10}\b)[1-9]\d{8,9}\b", "[REDACTED_ID]", data)
|
|
42
|
+
# Redact email addresses
|
|
43
|
+
masked = re.sub(r"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+", "[REDACTED_EMAIL]", masked)
|
|
44
|
+
return masked
|
|
45
|
+
|
|
46
|
+
return data
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def log_event(level: str, operation: str, context: Dict[str, Any]) -> None:
|
|
50
|
+
"""Prints a structured log line with sensitive fields automatically redacted."""
|
|
51
|
+
safe_ctx = redact_sensitive(context)
|
|
52
|
+
print(f"[{level.upper()}] {operation} | {safe_ctx}")
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Resilience utilities: retry with exponential backoff and safe execution."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from typing import Any, Callable, Optional, Tuple, Type
|
|
5
|
+
|
|
6
|
+
def with_retry(
|
|
7
|
+
action: Callable[[], Any],
|
|
8
|
+
max_attempts: int = 3,
|
|
9
|
+
initial_delay_sec: float = 0.2,
|
|
10
|
+
backoff_factor: float = 2.0,
|
|
11
|
+
allowed_exceptions: Tuple[Type[Exception], ...] = (Exception,),
|
|
12
|
+
on_retry: Optional[Callable[[int, Exception], None]] = None,
|
|
13
|
+
) -> Any:
|
|
14
|
+
"""Executes a callable with retries upon specified exceptions."""
|
|
15
|
+
delay = initial_delay_sec
|
|
16
|
+
last_error: Optional[Exception] = None
|
|
17
|
+
|
|
18
|
+
for attempt in range(1, max_attempts + 1):
|
|
19
|
+
try:
|
|
20
|
+
return action()
|
|
21
|
+
except allowed_exceptions as exc:
|
|
22
|
+
last_error = exc
|
|
23
|
+
if attempt == max_attempts:
|
|
24
|
+
break
|
|
25
|
+
if on_retry:
|
|
26
|
+
on_retry(attempt, exc)
|
|
27
|
+
time.sleep(delay)
|
|
28
|
+
delay *= backoff_factor
|
|
29
|
+
|
|
30
|
+
if last_error:
|
|
31
|
+
raise last_error
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Text processing and string normalization utilities."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
def clean_label(text: str) -> str:
|
|
6
|
+
"""Strips unicode whitespace, tabs, newlines, and leading asterisks/spaces."""
|
|
7
|
+
if not text:
|
|
8
|
+
return ""
|
|
9
|
+
# Replace non-breaking spaces and line breaks with single space
|
|
10
|
+
cleaned = re.sub(r"[\u00a0\r\n\t]+", " ", str(text))
|
|
11
|
+
# Strip leading whitespace and asterisks commonly used in required indicators
|
|
12
|
+
cleaned = re.sub(r"^[\s\*]+", "", cleaned)
|
|
13
|
+
return cleaned.strip()
|
|
14
|
+
|
|
15
|
+
def truncate_text(text: str, max_length: int = 80) -> str:
|
|
16
|
+
"""Truncates text safely with boundary check."""
|
|
17
|
+
if not text or len(text) <= max_length:
|
|
18
|
+
return text or ""
|
|
19
|
+
return text[:max_length].strip()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"device_name": "Desktop Chrome Standard",
|
|
3
|
+
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
|
|
4
|
+
"viewport": {
|
|
5
|
+
"width": 1400,
|
|
6
|
+
"height": 1100
|
|
7
|
+
},
|
|
8
|
+
"device_scale_factor": 1.0,
|
|
9
|
+
"is_mobile": false,
|
|
10
|
+
"has_touch": false,
|
|
11
|
+
"locale": "en-US",
|
|
12
|
+
"timezone_id": "UTC",
|
|
13
|
+
"geolocation": null,
|
|
14
|
+
"permissions": [],
|
|
15
|
+
"platform": "Win32",
|
|
16
|
+
"vendor": "Google Inc."
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"device_name": "Desktop Chrome Standard",
|
|
3
|
+
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
|
|
4
|
+
"viewport": {
|
|
5
|
+
"width": 1400,
|
|
6
|
+
"height": 1100
|
|
7
|
+
},
|
|
8
|
+
"device_scale_factor": 1.0,
|
|
9
|
+
"is_mobile": false,
|
|
10
|
+
"has_touch": false,
|
|
11
|
+
"locale": "en-US",
|
|
12
|
+
"timezone_id": "UTC",
|
|
13
|
+
"geolocation": null,
|
|
14
|
+
"permissions": [],
|
|
15
|
+
"platform": "Win32",
|
|
16
|
+
"vendor": "Google Inc."
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headless": true,
|
|
3
|
+
"default_timeout_ms": 45000,
|
|
4
|
+
"form_ready_timeout_ms": 10000,
|
|
5
|
+
"submission_wait_ms": 8000,
|
|
6
|
+
"expand_section_wait_ms": 800,
|
|
7
|
+
"screenshots_dir": "screenshots",
|
|
8
|
+
"cookies_path": null,
|
|
9
|
+
"data_path": null,
|
|
10
|
+
"proxy": null,
|
|
11
|
+
"geolocation": null
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headless": true,
|
|
3
|
+
"default_timeout_ms": 45000,
|
|
4
|
+
"form_ready_timeout_ms": 10000,
|
|
5
|
+
"submission_wait_ms": 8000,
|
|
6
|
+
"expand_section_wait_ms": 800,
|
|
7
|
+
"screenshots_dir": "screenshots",
|
|
8
|
+
"cookies_path": null,
|
|
9
|
+
"data_path": null,
|
|
10
|
+
"proxy": null,
|
|
11
|
+
"geolocation": null
|
|
12
|
+
}
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "webpilot-engine"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.4"
|
|
8
8
|
description = "WebPilot: Enterprise Autonomous Browser Engine, Universal Form Inspector & AI Agent Web Runtime"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -27,7 +27,7 @@ keywords = [
|
|
|
27
27
|
"process-isolation"
|
|
28
28
|
]
|
|
29
29
|
classifiers = [
|
|
30
|
-
"Development Status ::
|
|
30
|
+
"Development Status :: 4 - Beta",
|
|
31
31
|
"Intended Audience :: Developers",
|
|
32
32
|
"Topic :: Software Development :: Testing",
|
|
33
33
|
"Topic :: Internet :: WWW/HTTP :: Browsers",
|
|
@@ -45,6 +45,13 @@ dependencies = [
|
|
|
45
45
|
"python-dotenv>=1.0.0",
|
|
46
46
|
]
|
|
47
47
|
|
|
48
|
+
[project.urls]
|
|
49
|
+
Homepage = "https://github.com/AbdulkarimSSS/webpilot"
|
|
50
|
+
Documentation = "https://github.com/AbdulkarimSSS/webpilot#readme"
|
|
51
|
+
Repository = "https://github.com/AbdulkarimSSS/webpilot.git"
|
|
52
|
+
"Bug Tracker" = "https://github.com/AbdulkarimSSS/webpilot/issues"
|
|
53
|
+
Changelog = "https://github.com/AbdulkarimSSS/webpilot/blob/master/CHANGELOG.md"
|
|
54
|
+
|
|
48
55
|
[project.optional-dependencies]
|
|
49
56
|
dev = [
|
|
50
57
|
"pytest>=8.0.0",
|
|
@@ -54,7 +61,7 @@ dev = [
|
|
|
54
61
|
"Faker>=24.0.0",
|
|
55
62
|
]
|
|
56
63
|
mcp = [
|
|
57
|
-
"mcp>=1.0.0",
|
|
64
|
+
"mcp>=1.0.0,<2",
|
|
58
65
|
]
|
|
59
66
|
|
|
60
67
|
[project.scripts]
|
|
@@ -69,7 +76,10 @@ py-modules = ["cli", "mcp_server", "engine", "builder", "models", "exceptions"]
|
|
|
69
76
|
|
|
70
77
|
[tool.setuptools.packages.find]
|
|
71
78
|
where = ["."]
|
|
72
|
-
include = ["adapters*", "config*", "constants*", "core*", "orchestration*", "services*", "supervisor*", "validators*"]
|
|
79
|
+
include = ["adapters*", "common*", "config*", "constants*", "core*", "orchestration*", "services*", "supervisor*", "validators*"]
|
|
80
|
+
|
|
81
|
+
[tool.setuptools.package-data]
|
|
82
|
+
config = ["*.json"]
|
|
73
83
|
|
|
74
84
|
[tool.pytest.ini_options]
|
|
75
85
|
minversion = "8.0"
|
|
@@ -111,7 +111,7 @@ def run_interactive_shell(host: str = "127.0.0.1", port: int = 9333):
|
|
|
111
111
|
|
|
112
112
|
elif cmd == "upload":
|
|
113
113
|
if not arg:
|
|
114
|
-
print("[!] Error: upload path required, e.g. upload resume=
|
|
114
|
+
print("[!] Error: upload path required, e.g. upload resume=path/to/cv.pdf")
|
|
115
115
|
continue
|
|
116
116
|
req = SupervisorActionRequest(action="apply", upload_files=[arg.strip()])
|
|
117
117
|
res = client.execute(req)
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: webpilot-engine
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: WebPilot: Enterprise Autonomous Browser Engine, Universal Form Inspector & AI Agent Web Runtime
|
|
5
5
|
Author: Abdulkarim Salih, WebPilot Core Team
|
|
6
6
|
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/AbdulkarimSSS/webpilot
|
|
8
|
+
Project-URL: Documentation, https://github.com/AbdulkarimSSS/webpilot#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/AbdulkarimSSS/webpilot.git
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/AbdulkarimSSS/webpilot/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/AbdulkarimSSS/webpilot/blob/master/CHANGELOG.md
|
|
7
12
|
Keywords: webpilot,browser-runtime,ai-agent,web-automation,playwright,form-filler,ats-automation,sap-successfactors,workday,browser-supervisor,process-isolation
|
|
8
|
-
Classifier: Development Status ::
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
14
|
Classifier: Intended Audience :: Developers
|
|
10
15
|
Classifier: Topic :: Software Development :: Testing
|
|
11
16
|
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
@@ -28,7 +33,7 @@ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
|
28
33
|
Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
|
|
29
34
|
Requires-Dist: Faker>=24.0.0; extra == "dev"
|
|
30
35
|
Provides-Extra: mcp
|
|
31
|
-
Requires-Dist: mcp
|
|
36
|
+
Requires-Dist: mcp<2,>=1.0.0; extra == "mcp"
|
|
32
37
|
|
|
33
38
|
# WebPilot: Autonomous Multi-Tier Browser Automation Engine & AI Agent Web Runtime
|
|
34
39
|
|
|
@@ -13,7 +13,16 @@ adapters/dom_scripts.py
|
|
|
13
13
|
adapters/envelope_builder.py
|
|
14
14
|
adapters/live_session_manager.py
|
|
15
15
|
adapters/upload_adapter.py
|
|
16
|
+
common/__init__.py
|
|
17
|
+
common/cookies.py
|
|
18
|
+
common/logging.py
|
|
19
|
+
common/retry.py
|
|
20
|
+
common/text.py
|
|
16
21
|
config/__init__.py
|
|
22
|
+
config/device_profile.example.json
|
|
23
|
+
config/device_profile.json
|
|
24
|
+
config/settings.example.json
|
|
25
|
+
config/settings.json
|
|
17
26
|
config/settings.py
|
|
18
27
|
constants/__init__.py
|
|
19
28
|
constants/contracts.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{webpilot_engine-2.0.3 → webpilot_engine-2.0.4}/webpilot_engine.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|