agentic-stealth-browser 2.4.0__tar.gz → 2.5.0__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.
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/CHANGELOG.md +79 -18
- agentic_stealth_browser-2.5.0/CODE_OF_CONDUCT.md +70 -0
- agentic_stealth_browser-2.5.0/CONTRIBUTING.md +237 -0
- agentic_stealth_browser-2.5.0/MANIFEST.in +19 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/PKG-INFO +84 -21
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/README.md +83 -20
- agentic_stealth_browser-2.5.0/SECURITY.md +39 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/agentic_stealth_browser.egg-info/PKG-INFO +84 -21
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/agentic_stealth_browser.egg-info/SOURCES.txt +72 -1
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/agentic_stealth_browser.egg-info/top_level.txt +3 -0
- agentic_stealth_browser-2.5.0/assets/hn-demo.gif +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/behavior/human_behavior.py +7 -1
- agentic_stealth_browser-2.5.0/canary/__init__.py +8 -0
- agentic_stealth_browser-2.5.0/canary/badge_gen.py +48 -0
- agentic_stealth_browser-2.5.0/canary/dashboard_gen.py +77 -0
- agentic_stealth_browser-2.5.0/canary/history.py +101 -0
- agentic_stealth_browser-2.5.0/canary/readme_gen.py +54 -0
- agentic_stealth_browser-2.5.0/canary/runner.py +83 -0
- agentic_stealth_browser-2.5.0/canary/score.py +26 -0
- agentic_stealth_browser-2.5.0/canary/sites.py +91 -0
- agentic_stealth_browser-2.5.0/canary/templates/badge.svg.j2 +17 -0
- agentic_stealth_browser-2.5.0/canary/templates/dashboard.html.j2 +185 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/agent_browser.py +190 -89
- agentic_stealth_browser-2.5.0/docs/ATTACH_OVER_CDP.md +146 -0
- agentic_stealth_browser-2.5.0/docs/README.md +28 -0
- agentic_stealth_browser-2.5.0/docs/agentic-stealth-browser-analysis-report.md +93 -0
- agentic_stealth_browser-2.5.0/docs/canary/README.md +43 -0
- agentic_stealth_browser-2.5.0/docs/canary/badge.svg +17 -0
- agentic_stealth_browser-2.5.0/docs/canary/history.jsonl +1 -0
- agentic_stealth_browser-2.5.0/docs/canary/index.html +213 -0
- agentic_stealth_browser-2.5.0/docs/canary.md +43 -0
- agentic_stealth_browser-2.5.0/docs/plans/2026-06-01-v2.4.0-attach-mode-hardening.md +439 -0
- agentic_stealth_browser-2.5.0/docs/plans/2026-06-03-v2.5.0-real-backend-adapters.md +479 -0
- agentic_stealth_browser-2.5.0/docs/plans/misc/GOAL_MODE_HERMES_BROWSER_DASHBOARD.md +71 -0
- agentic_stealth_browser-2.5.0/docs/plans/misc/HN_POST.md +52 -0
- agentic_stealth_browser-2.5.0/docs/plans/misc/OPEN_SOURCE_READINESS.md +161 -0
- agentic_stealth_browser-2.5.0/docs/plans/misc/RELEASE_AUTONOMOUS_PLAN.md +115 -0
- agentic_stealth_browser-2.5.0/examples/recipes/01_cloudflare_bypass.py +32 -0
- agentic_stealth_browser-2.5.0/examples/recipes/02_linkedin_search.py +48 -0
- agentic_stealth_browser-2.5.0/examples/recipes/03_amazon_product.py +49 -0
- agentic_stealth_browser-2.5.0/examples/recipes/README.md +18 -0
- agentic_stealth_browser-2.5.0/mcp_security.py +411 -0
- agentic_stealth_browser-2.5.0/plugins/__init__.py +6 -0
- agentic_stealth_browser-2.5.0/plugins/template/__init__.py +4 -0
- agentic_stealth_browser-2.5.0/plugins/template/plugin.py +85 -0
- agentic_stealth_browser-2.5.0/production/adapters/__init__.py +111 -0
- agentic_stealth_browser-2.5.0/production/adapters/_jsonrpc_stdio.py +87 -0
- agentic_stealth_browser-2.5.0/production/adapters/agentic_stealth_mcp.py +240 -0
- agentic_stealth_browser-2.5.0/production/adapters/base.py +118 -0
- agentic_stealth_browser-2.5.0/production/adapters/cdp_bridge.py +197 -0
- agentic_stealth_browser-2.5.0/production/adapters/playwright_mcp.py +251 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/cli.py +16 -15
- agentic_stealth_browser-2.5.0/production/dashboard_adapter_bridge.py +76 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/hermes_dashboard.py +73 -1
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/mcp_input_validator.py +8 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/mcp_server.py +113 -25
- agentic_stealth_browser-2.5.0/production/sdk/__init__.py +14 -0
- agentic_stealth_browser-2.5.0/production/sdk/client.py +305 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/pyproject.toml +31 -1
- agentic_stealth_browser-2.5.0/scripts/canary_run.py +54 -0
- agentic_stealth_browser-2.5.0/scripts/evaluate_stealth.py +286 -0
- agentic_stealth_browser-2.5.0/scripts/generate-demo-gif.py +214 -0
- agentic_stealth_browser-2.5.0/scripts/health_check.py +257 -0
- agentic_stealth_browser-2.5.0/scripts/hn-demo.py +61 -0
- agentic_stealth_browser-2.5.0/scripts/make-gif.py +80 -0
- agentic_stealth_browser-2.5.0/scripts/migrate_v1_to_v2.py +154 -0
- agentic_stealth_browser-2.5.0/scripts/perf_benchmark.py +290 -0
- agentic_stealth_browser-2.5.0/scripts/setup_rbb.sh +220 -0
- agentic_stealth_browser-2.5.0/stealth/__init__.py +0 -0
- agentic_stealth_browser-2.5.0/tests/test_adapter_agentic_stealth_mcp.py +389 -0
- agentic_stealth_browser-2.5.0/tests/test_adapter_cdp_bridge.py +295 -0
- agentic_stealth_browser-2.5.0/tests/test_adapter_playwright_mcp.py +416 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_attach_over_cdp.py +40 -22
- agentic_stealth_browser-2.5.0/tests/test_backend_adapter_contract.py +293 -0
- agentic_stealth_browser-2.5.0/tests/test_dashboard_protocol_bridge.py +170 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_hermes_dashboard.py +42 -2
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_human_behavior_fuzz.py +8 -10
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_mcp_server_runtime.py +168 -2
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_mcp_stealth_workflows.py +4 -1
- agentic_stealth_browser-2.5.0/tests/test_mcp_url_safety.py +100 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_phase7_fixes.py +24 -5
- agentic_stealth_browser-2.5.0/workflows/library/auto-session-test.yaml +4 -0
- agentic_stealth_browser-2.5.0/workflows/library/common/login.yaml +2 -0
- agentic_stealth_browser-2.5.0/workflows/library/common/verify-email.yaml +2 -0
- agentic_stealth_browser-2.5.0/workflows/library/linkedin/send-connection-request.yaml +63 -0
- agentic_stealth_browser-2.5.0/workflows/library/meta-test.yaml +2 -0
- agentic_stealth_browser-2.5.0/workflows/library/simple-test.yaml +7 -0
- agentic_stealth_browser-2.5.0/workflows/library/teach-test/test-teach.yaml +8 -0
- agentic_stealth_browser-2.5.0/workflows/library/upwork/add-portfolio-item.yaml +54 -0
- agentic_stealth_browser-2.5.0/workflows/library/upwork/apply.yaml +2 -0
- agentic_stealth_browser-2.5.0/workflows/library/upwork/edit-title.yaml +40 -0
- agentic_stealth_browser-2.5.0/workflows/library/upwork/submit-proposal.yaml +48 -0
- agentic_stealth_browser-2.5.0/workflows/library/upwork/update-rate.yaml +40 -0
- agentic_stealth_browser-2.4.0/MANIFEST.in +0 -9
- agentic_stealth_browser-2.4.0/examples/recipes/README.md +0 -10
- agentic_stealth_browser-2.4.0/tests/test_mcp_url_safety.py +0 -56
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/.env.example +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/LICENSE +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/agentic_stealth_browser.egg-info/dependency_links.txt +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/agentic_stealth_browser.egg-info/entry_points.txt +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/agentic_stealth_browser.egg-info/requires.txt +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/ai/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/ai/ai_hooks.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/audit/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/audit/logger.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/behavior/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/behavior/adaptive_tuner.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/behavior/orchestration.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/behavior/persona_rotator.py +0 -0
- {agentic_stealth_browser-2.4.0/core → agentic_stealth_browser-2.5.0/canary}/py.typed +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/account_health.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/account_warming.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/connection_pool.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/error_messages.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/feature_flags.py +0 -0
- /agentic_stealth_browser-2.4.0/proxy/__init__.py → /agentic_stealth_browser-2.5.0/core/py.typed +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/session_checkpoint.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/core/types.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/examples/recipes/linkedin.md +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/linkedin/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/linkedin/actions.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/Dockerfile +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/approval_gate.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/audit_enrichment.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/deprecations.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/docker-compose.yml +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/docker-healthcheck.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/mcp_session_isolation.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/metrics.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/otel_export.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/policy_engine.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/profiler.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/rate_limiter.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/production/workflow_orchestrator.py +0 -0
- {agentic_stealth_browser-2.4.0/recovery → agentic_stealth_browser-2.5.0/proxy}/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/proxy/proxy_manager.py +0 -0
- {agentic_stealth_browser-2.4.0/scraping → agentic_stealth_browser-2.5.0/recovery}/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/recovery/anti_block_orchestrator.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/recovery/detectors.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/recovery/explain_blocked.py +0 -0
- {agentic_stealth_browser-2.4.0/sessions → agentic_stealth_browser-2.5.0/scraping}/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/scraping/scraper.py +0 -0
- {agentic_stealth_browser-2.4.0/stealth → agentic_stealth_browser-2.5.0/sessions}/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/sessions/cookie_manager.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/sessions/session_manager.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/setup.cfg +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/advanced_stealth.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/cache.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/firefox_adapter.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/headers.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/presets.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/profiles.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/tls_fingerprint.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/stealth/tls_ja3_ja4.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/debug_nowsecure.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/detection_check.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/detection_runner.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/fingerprint_scorecard.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/run_detection_tests.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_account_health.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_account_warming.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_adaptive_tuner.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_basic.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_cdp_snapshots.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_connection_pool.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_contract_agent_browser.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_cookie_manager_unit.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_detectors.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_differential.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_docker_config.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_e2e_anti_block_recovery.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_e2e_protected_sites_placeholder.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_golden_master.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_integration_modules.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_linkedin_actions.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_mcp_contract.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_metrics_collector_unit.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_mutation_stealth.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_persona_rotator.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_player.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_proxy_config_unit.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_proxy_manager.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_rate_limiter_unit.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_recorder.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_recovery.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_recovery_phase1.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_recovery_state_machine.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_rehearsal_validation.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_selector_auto_heal.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_session_checkpoint.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_stealth_cache.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_stealth_coverage.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_stealth_modules.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_stress_multi_account.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_tls_ja3_ja4.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_workflow_orchestrator.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_workflow_schema.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_workflow_schema_unit.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/tests/test_workflow_versioning.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/__init__.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/action_interpreter.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/player.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/recorder.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/recovery.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/schema.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/selector_generator.py +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/test-echo.yaml +0 -0
- {agentic_stealth_browser-2.4.0 → agentic_stealth_browser-2.5.0}/workflows/variable_resolver.py +0 -0
|
@@ -7,6 +7,85 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
## [2.5.0] — Real Dashboard Backend Adapters (#444) (2026-06-07)
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **`BackendAdapter` Protocol + `Capability` enum** (`production/adapters/base.py:84`): runtime-checkable protocol with `launch`/`close`/`navigate`/`click`/`fill`/`screenshot`/`status`/`capabilities` surface. All three backends (M1/M2/M3) implement it. New `AdapterLaunchError` and `AdapterCapabilityError` exception types; `register_adapter` enforces non-empty string names. (#444 M0)
|
|
16
|
+
- **`CDPBridgeAdapter`** (`production/adapters/cdp_bridge.py`): Playwright `connect_over_cdp` over WebSocket. Used for adopted-context / WSL-host workflows where the operator already owns a browser process. (#444 M1)
|
|
17
|
+
- **`PlaywrightMCPAdapter`** (`production/adapters/playwright_mcp.py`): stdio subprocess + MCP JSON-RPC. Spawns `npx @playwright/mcp` with an explicit env allowlist (PATH, HOME) and a 16 MB `MAX_FRAME_BYTES` frame cap. (#444 M2)
|
|
18
|
+
- **`AgenticStealthMCPAdapter`** (`production/adapters/agentic_stealth_mcp.py`): stdio subprocess + MCP JSON-RPC, round-trips through the bundled `production.mcp_server` runtime. Same env allowlist, frame cap, and stderr-drain guarantees as M2. (#444 M3)
|
|
19
|
+
- **Dashboard backend wiring (M4)**: `BrowserRuntimeManager` resolves the configured backend through the adapter registry, records an audit event on backend switch, surfaces negotiated capabilities in dashboard status, and rejects unsupported actions with a backend-specific error. `production/dashboard_adapter_bridge.py` is now a thin shim that re-exports the three M1–M3 adapters. (#444 M4)
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- `production/hermes_dashboard.py` re-exports `BackendAdapter` from `production/adapters/`.
|
|
23
|
+
- `production/dashboard_adapter_bridge.py` thin shim replaces the three alias backends.
|
|
24
|
+
- `MANIFEST.in`: ships `assets/*.{gif,png,jpg,svg}` (demo GIF), `docs/`, `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md`, `SECURITY.md` (sdist previously dropped the demo GIF and the entire `docs/` tree).
|
|
25
|
+
- `README.md`: added "What is this / When to use / When NOT to use" block at top, honest comparison table (region client-hello profiles, not full uTLS), install-from-source section, full project tree + doc index. Dropped unverified test-count badge and Buy Me A Coffee. 177 → 238 lines.
|
|
26
|
+
- New `docs/README.md` operator/reference/planning index. Root-level `*PLAN.md` / `*READINESS.md` / `*DASHBOARD.md` / `HN_POST.md` moved to `docs/plans/misc/` as historical.
|
|
27
|
+
- Examples rewritten for honesty and reproducibility: `01_cloudflare_bypass.py` (nowsecure.nl + screenshot), `02_linkedin_search.py` (`linkedin_2026` preset + webdriver check + DDG), `03_amazon_product.py` (product → title + price). `recipes/README.md` table updated.
|
|
28
|
+
- `pyproject.toml` version 2.4.1 → 2.5.0.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
- **#444 M0 review (showstoppers)**:
|
|
32
|
+
- **S1 capability gating**: M2/M3 `navigate`/`click`/`fill`/`screenshot` now call `self.supports()` and raise `AdapterCapabilityError` if the adapter doesn't declare the capability (enforces `base.py:84` protocol contract). New `_require_capability()` helper on each adapter.
|
|
33
|
+
- **S2 stderr drain**: M2/M3 `stderr=PIPE` is now drained by a background task started right after `spawn` and cancelled in `close()`. A noisy child no longer fills the ~64 KB kernel pipe buffer, blocks on its next stderr write, hangs the handshake, and triggers a slow SIGKILL on close.
|
|
34
|
+
- **F1 stale state on retry**: after MCP handshake failure, `terminate_subprocess()` is called and `self._proc` / `self._client` are cleared. A caller that catches `AdapterLaunchError` and then calls `close()` no longer operates on a dead `Process` handle.
|
|
35
|
+
- **#444 M0 review (smaller)**:
|
|
36
|
+
- **F2 frame cap**: `_jsonrpc_stdio.readline()` now enforces `MAX_FRAME_BYTES = 16 MB` and raises `ConnectionError` on overflow. A misbehaving server emitting a multi-GB line no longer OOMs the client.
|
|
37
|
+
- **F3 env allowlist**: both stdio adapters now pass an explicit `env={PATH, HOME}` to `asyncio.create_subprocess_exec` instead of inheriting the operator's full environment (`OPENAI_API_KEY`, `AWS_*`, `DATABASE_URL`, ...).
|
|
38
|
+
- **A3 dead tautology**: `cdp_bridge.screenshot()` had a defensive `Capability.SCREENSHOT` check that could never fire (always in `capabilities()`). Branch removed; M0 contract is the only contract that matters.
|
|
39
|
+
- **M0 code-quality review (17abc50)**: exception types narrowed to library-specific where appropriate, `isinstance` coverage tightened, defensive tautology branches removed, transport teardown made symmetric with launch.
|
|
40
|
+
- **Adapter capability gating**: now consistent across M1/M2/M3 — each action is contractually declared, not assumed.
|
|
41
|
+
- **Ruff/format housekeeping** (4432701): 12 ruff format issues + 1 unused import fixed.
|
|
42
|
+
|
|
43
|
+
### Tests / CI
|
|
44
|
+
- `tests/test_backend_adapter_contract.py` — new contract test pinning the M0 Protocol surface, `Capability` enum members, and `register_adapter` duplicate/empty/non-string rejection.
|
|
45
|
+
- `tests/test_adapter_cdp_bridge.py`, `tests/test_adapter_playwright_mcp.py`, `tests/test_adapter_agentic_stealth_mcp.py` — new per-adapter tests covering launch, capability negotiation, action gating, stderr drain, env allowlist, and close lifecycle.
|
|
46
|
+
- `tests/test_dashboard_protocol_bridge.py` — new dashboard-wiring test (M4): audit event on backend switch, capability surface, unsupported-action rejection.
|
|
47
|
+
- `pytest -q`: 1025 collected, 1023 passed, 2 e2e skipped, 0 failed (139 s; baseline maintained).
|
|
48
|
+
- `ruff check` + `ruff format --check` clean across 159 Python files.
|
|
49
|
+
|
|
50
|
+
Closes #444.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## [2.4.1] — v2.4.0 Stabilization Patch (2026-06-03)
|
|
55
|
+
|
|
56
|
+
### Fixed / Security / Reliability (P0/P1 per #459)
|
|
57
|
+
- **#454** MCP nav/scrape: `is_url_safe` now fails closed for non-http(s) schemes (`file:`, `javascript:`, `data:`, `ftp:`, ...), missing hosts, DNS errors, and empty resolutions. Unsafe inputs raise `MCP_SSRF_BLOCKED` before any browser navigation. Added unit matrix + dispatch regression tests.
|
|
58
|
+
- **#455** MCP runtime: declarative input validation from `production/mcp_input_validator.py` is now enforced in `tools/call` dispatch (types, lengths, ranges, required, patterns, `additionalProperties: false`). Validation errors return stable `MCP_VALIDATION_ERROR` without invoking handlers. Schema/validator parity and dispatch tests added.
|
|
59
|
+
- **#451** CDP attach: adopted user tabs (`new_context=False`) are no longer closed on `close()`. New `_owns_page` tracking + conditional teardown; adopted contexts/pages preserved per contract. Updated tests + docs.
|
|
60
|
+
- **#452** CDP attach: post-`connect_over_cdp` failures (bad context_index, new_context, page create, stealth) now best-effort rollback `_pw`, `_remote_browser`, owned ctxs (never adopted), and reset attach flags for clean retry.
|
|
61
|
+
- **#453** CDP attach: attach path now initializes `human`, `orchestrator`, `logger`, `scraper`, `ai`, `recovery` (with attach degradation notes). `safe_goto`/`safe_click`/`safe_type` + MCP `stealth_scrape` now operational on attached sessions.
|
|
62
|
+
- **#458** Hermes dashboard: startup rejects default/empty/`change-me` password when binding to non-loopback (0.0.0.0, RFC1918, public, IPv6 non-loop). Loopback dev still convenient. Added guard tests.
|
|
63
|
+
- **#457** CLI `scrape`: removed double `launch()` (async-with already launches; now passes preset/region via ctor so aenter applies them). Exactly one launch + one close. Aligned all user-facing names/help/examples to `agentic-stealth-browser`. Mocked regression test.
|
|
64
|
+
- **#456** Packaging: `pyproject.toml` now includes `production.*`, `workflows.*`, `plugins.*`. `MANIFEST.in` extended. CI verify expanded for SDK import + bundled workflow discovery from clean cwd. MCP server workflow root switched to user-writable `~/.agentic-browser/...` + bundled discovery fallback for install safety.
|
|
65
|
+
- **#447** MCP version: `SERVER_VERSION` now derives from `importlib.metadata.version("agentic-stealth-browser")` (falls back to 2.4.1); no longer stale.
|
|
66
|
+
- **#448** CDP attach gate: relaxed RFC1918 rejection under `allow_remote=true` for attach (WSL host IPs are intentionally private); link-local/cloud still blocked. Nav remains strict. Reconciled docs + tests with real WSL workflow.
|
|
67
|
+
- **#450** Docs/metadata: toned down TLS/JA3/JA4 claims to "region client-hello profiles (process-level)"; attach degradation already documented the limits. No wire-level full-stack spoofing claimed.
|
|
68
|
+
- **#449** Release hygiene: refreshed counts, changelog, version to 2.4.1, support notes, publish smoke.
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
- Runtime helpers and ownership tracking for attach mode.
|
|
72
|
+
- Validation dispatch + matrix tests; single-launch CLI mock test; dashboard bind security tests.
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
- `pyproject.toml` version 2.4.0 → 2.4.1; packages.find + MANIFEST.in for full artifacts.
|
|
76
|
+
- Attach lifecycle docs/examples (no more auto-launch + attach in same `async with`).
|
|
77
|
+
- MCP attach remote safety contract + tests for WSL compatibility.
|
|
78
|
+
|
|
79
|
+
### Tests / CI
|
|
80
|
+
- All non-e2e/non-live green.
|
|
81
|
+
- Focused attach + MCP safety + validation + CLI mocks + dashboard guard.
|
|
82
|
+
- `ruff check` + `ruff format --check` pass.
|
|
83
|
+
- Wheel build + import + discovery smoke updated in publish.yml.
|
|
84
|
+
|
|
85
|
+
Closes #447, #448, #449, #450, #451, #452, #453, #454, #455, #456, #457, #458, #459 (patch scope).
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
10
89
|
## [2.4.0] — Attach-Mode Hardening (2026-06-01)
|
|
11
90
|
|
|
12
91
|
### Fixed
|
|
@@ -35,24 +114,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
35
114
|
|
|
36
115
|
---
|
|
37
116
|
|
|
38
|
-
## [Unreleased]
|
|
39
|
-
|
|
40
|
-
### Added
|
|
41
|
-
- **`AgentBrowser.attach_over_cdp(cdp_url, ...)`**: connect to an already-running
|
|
42
|
-
browser exposed via Chrome DevTools Protocol (e.g. Chrome launched with
|
|
43
|
-
`--remote-debugging-port=9222`) instead of spawning a new Chromium. Complements
|
|
44
|
-
the existing `debug_cdp=True` launch flag — that one *exposes* an endpoint, this
|
|
45
|
-
one *consumes* one. Primary use case: drive a real desktop browser from a
|
|
46
|
-
different host (WSL → Windows, container → host, dev box → remote display).
|
|
47
|
-
Runtime stealth init scripts (navigator/canvas/WebGL/audio patches) are still
|
|
48
|
-
injected on the chosen context; launch-time stealth (TLS/JA3, regional preset,
|
|
49
|
-
user-data-dir) is unavailable in attach mode and listed in the return payload's
|
|
50
|
-
`degradation` field. `close()` disconnects without terminating the external
|
|
51
|
-
browser. (#attach-cdp)
|
|
52
|
-
- **MCP tool `stealth_attach_over_cdp`**: surfaces `attach_over_cdp` through the
|
|
53
|
-
MCP server. Defaults to loopback-only; non-loopback hosts require explicit
|
|
54
|
-
`allow_remote=true` and raise `MCP_REMOTE_CDP_BLOCKED` otherwise. (#attach-cdp)
|
|
55
|
-
|
|
56
117
|
## [2.3.0] — Show HN & Community Launch (2026-05-28)
|
|
57
118
|
|
|
58
119
|
### Added
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
* Demonstrating empathy and kindness toward other people
|
|
21
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
* Giving and gracefully accepting constructive feedback
|
|
23
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
* Focusing on what is best not just for us as individuals, but for the overall
|
|
26
|
+
community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
|
31
|
+
any kind
|
|
32
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
* Public or private harassment
|
|
34
|
+
* Publishing others' private information, such as a physical or email address,
|
|
35
|
+
without their explicit permission
|
|
36
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
49
|
+
decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
|
|
56
|
+
## Enforcement
|
|
57
|
+
|
|
58
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
59
|
+
reported to the community leaders responsible for enforcement at
|
|
60
|
+
[GitHub Issues](https://github.com/shanewas/agentic-stealth-browser/issues).
|
|
61
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
62
|
+
|
|
63
|
+
## Attribution
|
|
64
|
+
|
|
65
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
66
|
+
version 2.1, available at
|
|
67
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
68
|
+
|
|
69
|
+
[homepage]: https://www.contributor-covenant.org
|
|
70
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# CONTRIBUTING.md (#55)
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to the Agentic Stealth Browser! This guide will help you get started.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Development Setup
|
|
8
|
+
|
|
9
|
+
### 1. Clone the Repository
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/shanewas/agentic-stealth-browser.git
|
|
13
|
+
cd agentic-stealth-browser
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 2. Create a Virtual Environment
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
python3 -m venv .venv
|
|
20
|
+
source .venv/bin/activate
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 3. Install Dependencies
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install -e ".[dev]"
|
|
27
|
+
playwright install chromium
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 4. Run Tests
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Run all tests
|
|
34
|
+
pytest tests/ -v
|
|
35
|
+
|
|
36
|
+
# Run specific test files
|
|
37
|
+
pytest tests/test_stealth_modules.py -v
|
|
38
|
+
pytest tests/test_contract_agent_browser.py -v
|
|
39
|
+
pytest tests/test_recovery_phase1.py -v
|
|
40
|
+
|
|
41
|
+
# Run with coverage
|
|
42
|
+
pytest tests/ --cov=core --cov=stealth --cov=recovery --cov=behavior
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Code Style
|
|
48
|
+
|
|
49
|
+
### Formatting
|
|
50
|
+
|
|
51
|
+
We use standard Python conventions:
|
|
52
|
+
- 4-space indentation
|
|
53
|
+
- Maximum line length: 120 characters
|
|
54
|
+
- Type hints for all public APIs
|
|
55
|
+
- Docstrings for all public methods
|
|
56
|
+
|
|
57
|
+
### Naming Conventions
|
|
58
|
+
|
|
59
|
+
- Classes: `PascalCase` (e.g., `AgentBrowser`, `StealthConfig`)
|
|
60
|
+
- Functions/Methods: `snake_case` (e.g., `safe_goto`, `warm_up_before_work`)
|
|
61
|
+
- Constants: `UPPER_SNAKE_CASE` (e.g., `DEFAULT_PERSONA`, `MAX_RETRIES`)
|
|
62
|
+
- Private methods: Leading underscore (e.g., `_run_step`, `_check_circuit_breaker`)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Making Changes
|
|
67
|
+
|
|
68
|
+
### 1. Create a Branch
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git checkout -b feat/your-feature-name
|
|
72
|
+
# or
|
|
73
|
+
git checkout -b fix/issue-description
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. Make Your Changes
|
|
77
|
+
|
|
78
|
+
- Follow the existing code style
|
|
79
|
+
- Add tests for new functionality
|
|
80
|
+
- Update documentation if needed
|
|
81
|
+
|
|
82
|
+
### 3. Run Tests
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Ensure all tests pass
|
|
86
|
+
pytest tests/ -v
|
|
87
|
+
|
|
88
|
+
# Check for any import issues
|
|
89
|
+
python -c "from core.agent_browser import AgentBrowser"
|
|
90
|
+
python -c "from stealth.advanced_stealth import get_stealth_script"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 4. Commit Your Changes
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
git add .
|
|
97
|
+
git commit -m "feat: description of your change
|
|
98
|
+
|
|
99
|
+
More detailed description if needed.
|
|
100
|
+
|
|
101
|
+
Closes #123"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 5. Push and Create a Pull Request
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
git push origin your-branch-name
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then open a PR on GitHub.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Pull Request Guidelines
|
|
115
|
+
|
|
116
|
+
### Title Format
|
|
117
|
+
|
|
118
|
+
- `feat: ` for new features
|
|
119
|
+
- `fix: ` for bug fixes
|
|
120
|
+
- `docs: ` for documentation changes
|
|
121
|
+
- `test: ` for test additions/changes
|
|
122
|
+
- `refactor: ` for code refactoring
|
|
123
|
+
- `perf: ` for performance improvements
|
|
124
|
+
- `security: ` for security fixes
|
|
125
|
+
|
|
126
|
+
### Description
|
|
127
|
+
|
|
128
|
+
Include:
|
|
129
|
+
- What this PR does
|
|
130
|
+
- Why this change is needed
|
|
131
|
+
- Any related issues (e.g., "Closes #123")
|
|
132
|
+
- Testing instructions
|
|
133
|
+
|
|
134
|
+
### Requirements
|
|
135
|
+
|
|
136
|
+
- [ ] All tests pass
|
|
137
|
+
- [ ] New code has tests
|
|
138
|
+
- [ ] Documentation is updated (if applicable)
|
|
139
|
+
- [ ] No sensitive data in code or commits
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Architecture Overview
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
agentic-stealth-browser/
|
|
147
|
+
├── core/
|
|
148
|
+
│ ├── agent_browser.py # Main AgentBrowser class
|
|
149
|
+
│ ├── error_messages.py # User-friendly error messages
|
|
150
|
+
│ └── types.py # Type hints and stubs
|
|
151
|
+
├── stealth/
|
|
152
|
+
│ ├── advanced_stealth.py # Stealth script generation
|
|
153
|
+
│ ├── tls_fingerprint.py # TLS profile management
|
|
154
|
+
│ ├── headers.py # HTTP header spoofing
|
|
155
|
+
│ ├── profiles.py # Persona/DeviceProfile system
|
|
156
|
+
│ └── presets.py # Platform presets
|
|
157
|
+
├── behavior/
|
|
158
|
+
│ ├── human_behavior.py # Human-like behavior simulation
|
|
159
|
+
│ └── orchestration.py # Behavior orchestration
|
|
160
|
+
├── recovery/
|
|
161
|
+
│ ├── anti_block_orchestrator.py # Block detection & recovery
|
|
162
|
+
│ └── explain_blocked.py # Block explanation
|
|
163
|
+
├── proxy/
|
|
164
|
+
│ └── proxy_manager.py # Proxy management & rotation
|
|
165
|
+
├── sessions/
|
|
166
|
+
│ ├── session_manager.py # Session management
|
|
167
|
+
│ └── cookie_manager.py # Cookie management
|
|
168
|
+
├── production/
|
|
169
|
+
│ ├── metrics.py # Metrics collection
|
|
170
|
+
│ ├── rate_limiter.py # Rate limiting
|
|
171
|
+
│ ├── cli.py # CLI entry point
|
|
172
|
+
│ └── agent_orchestrator.py # Multi-agent orchestration
|
|
173
|
+
├── audit/
|
|
174
|
+
│ └── logger.py # Audit logging
|
|
175
|
+
├── scraping/
|
|
176
|
+
│ └── scraper.py # Stealth scraping
|
|
177
|
+
├── ai/
|
|
178
|
+
│ └── ai_hooks.py # AI integration hooks
|
|
179
|
+
├── tests/ # Test suite
|
|
180
|
+
# (documentation lives in README.md and git history)
|
|
181
|
+
└── mcp_security.py # MCP security hardening
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Adding New Features
|
|
187
|
+
|
|
188
|
+
### New Stealth Patches
|
|
189
|
+
|
|
190
|
+
1. Add the patch to `stealth/advanced_stealth.py`
|
|
191
|
+
2. Add tests to `tests/test_stealth_modules.py`
|
|
192
|
+
3. Update relevant sections in README.md if behavior changes
|
|
193
|
+
|
|
194
|
+
### New Platform Preset
|
|
195
|
+
|
|
196
|
+
1. Add the preset to `stealth/presets.py`
|
|
197
|
+
2. Add a recipe to `README.md`
|
|
198
|
+
3. Test against the target site
|
|
199
|
+
|
|
200
|
+
### New Recovery Strategy
|
|
201
|
+
|
|
202
|
+
1. Update `PLATFORM_STRATEGIES` in `recovery/anti_block_orchestrator.py`
|
|
203
|
+
2. Add tests to `tests/test_recovery_phase1.py`
|
|
204
|
+
3. Document rate limiting behavior changes in README.md or relevant code comments
|
|
205
|
+
|
|
206
|
+
### New Human Behavior
|
|
207
|
+
|
|
208
|
+
1. Add the behavior to `behavior/human_behavior.py`
|
|
209
|
+
2. Respect `self.realism_level` for CI/light mode
|
|
210
|
+
3. Add tests
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Reporting Issues
|
|
215
|
+
|
|
216
|
+
When reporting a bug, include:
|
|
217
|
+
- Python version
|
|
218
|
+
- Playwright version
|
|
219
|
+
- Error message and stack trace
|
|
220
|
+
- Code snippet that reproduces the issue
|
|
221
|
+
- Debug report (`await browser.debug_report(print_report=True)`)
|
|
222
|
+
- Health status (`await browser.get_health_status()`)
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Security
|
|
227
|
+
|
|
228
|
+
If you discover a security vulnerability:
|
|
229
|
+
1. **Do not** open a public issue
|
|
230
|
+
2. Email the maintainer directly
|
|
231
|
+
3. Include steps to reproduce and potential impact
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
include CHANGELOG.md
|
|
4
|
+
include CODE_OF_CONDUCT.md
|
|
5
|
+
include CONTRIBUTING.md
|
|
6
|
+
include SECURITY.md
|
|
7
|
+
include .env.example
|
|
8
|
+
|
|
9
|
+
include assets/*.gif assets/*.png assets/*.jpg assets/*.svg
|
|
10
|
+
|
|
11
|
+
recursive-include docs *.md *.html *.svg *.jsonl
|
|
12
|
+
recursive-include stealth *.js *.json
|
|
13
|
+
recursive-include production Dockerfile docker-healthcheck.py
|
|
14
|
+
recursive-include examples *.md *.py *.txt
|
|
15
|
+
recursive-include tests *.py *.json
|
|
16
|
+
recursive-include workflows *.yaml *.yml
|
|
17
|
+
recursive-include plugins *.py
|
|
18
|
+
recursive-include production/sdk *.py
|
|
19
|
+
recursive-include scripts *.sh *.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentic-stealth-browser
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Production-grade, human-mimicking browser automation framework for autonomous agents. Survives modern anti-bot systems.
|
|
5
5
|
Author-email: Shane W <shanewas@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -45,15 +45,25 @@ Dynamic: license-file
|
|
|
45
45
|
[](LICENSE)
|
|
46
46
|
[](https://www.python.org/downloads/)
|
|
47
47
|
[](https://pypi.org/project/agentic-stealth-browser/)
|
|
48
|
-
[](tests/)
|
|
49
48
|
[](https://github.com/shanewas/agentic-stealth-browser)
|
|
50
|
-
[](https://buymeacoffee.com/shanewas)
|
|
51
49
|
|
|
52
50
|
<p align="center">
|
|
53
51
|
<img src="assets/hn-demo.gif" alt="Agentic Stealth Browser Demo" width="90%">
|
|
54
52
|
</p>
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
## What is this
|
|
55
|
+
|
|
56
|
+
A production-grade stealth browser automation library for Python, built on Playwright.
|
|
57
|
+
It survives modern anti-bot systems (Cloudflare, LinkedIn, Amazon, etc.) by looking
|
|
58
|
+
convincingly human at every layer — TLS, navigator, WebGL/Canvas, behavior, recovery.
|
|
59
|
+
|
|
60
|
+
**When to use it** — you are building an autonomous agent, scraper, or operator tool
|
|
61
|
+
that needs to pass bot detection in headless mode on protected sites.
|
|
62
|
+
|
|
63
|
+
**When NOT to use it** — you only need to scrape public, unprotected pages (use
|
|
64
|
+
`httpx` + `selectolax` or `playwright` directly). You need a real uTLS stack at the
|
|
65
|
+
wire level (use `curl_cffi`). You need CAPTCHA solving (this project intentionally
|
|
66
|
+
stops at detection + intervention; see Limitations below).
|
|
57
67
|
|
|
58
68
|
```bash
|
|
59
69
|
pip install agentic-stealth-browser
|
|
@@ -66,7 +76,7 @@ from core.agent_browser import AgentBrowser
|
|
|
66
76
|
async with AgentBrowser(session_name="demo") as browser:
|
|
67
77
|
await browser.launch(headless=True)
|
|
68
78
|
await browser.safe_goto("https://bot.sannysoft.com")
|
|
69
|
-
#
|
|
79
|
+
# passes WebGL, Canvas, AudioContext, WebRTC, and TLS fingerprint checks
|
|
70
80
|
```
|
|
71
81
|
|
|
72
82
|
---
|
|
@@ -77,14 +87,39 @@ Sites don't just check your User-Agent anymore. They check *everything*:
|
|
|
77
87
|
|
|
78
88
|
| Attack Surface | Vanilla Playwright | This library |
|
|
79
89
|
|---|---|---|
|
|
80
|
-
| **TLS handshake** (JA3/JA4
|
|
90
|
+
| **TLS handshake** (client hello / JA3/JA4-ish) | Standard Python TLS — instantly identifiable | Region-spoofed TLS profile (process-level, not custom uTLS) |
|
|
81
91
|
| **Navigator APIs** (`navigator.webdriver`, `plugins`, `languages`) | Leaks automation flags everywhere | Every property patched before first paint |
|
|
82
92
|
| **WebGL / Canvas fingerprint** | Headless GPU renders differently | Consistent buffers across sessions |
|
|
83
93
|
| **Human behavior** | Robotic clicks, instant typing | Bézier mouse curves, variable speed, fatigue simulation |
|
|
84
94
|
| **Auto-recovery** | None — blocks = failure | CAPTCHA detection → proxy rotation → retry chain |
|
|
85
95
|
| **Account warming** | Nothing | 14-day graduated ramp-up per account |
|
|
86
96
|
|
|
87
|
-
Result: **passes bot.sannysoft.com, pixelscan.net, and CreepJS** with zero flags in
|
|
97
|
+
Result: **passes bot.sannysoft.com, pixelscan.net, and CreepJS** with zero flags in
|
|
98
|
+
headless mode (detection canaries run every 4 hours via `docs/canary.md`).
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Limitations & honest claims
|
|
103
|
+
|
|
104
|
+
This library is opinionated and has real limits. Operators should know them up front:
|
|
105
|
+
|
|
106
|
+
- **Not a real uTLS stack.** TLS fingerprinting is process-level (region-matched
|
|
107
|
+
client-hello, init-script negotiation). It is *not* `curl_cffi`-grade wire-level
|
|
108
|
+
impersonation. Attach mode (CDP) degrades further: the host browser's TLS is whatever
|
|
109
|
+
the user already has.
|
|
110
|
+
- **Headless detection is a moving target.** Detection vendors change heuristics
|
|
111
|
+
weekly. This project runs a 4-hourly detection canary
|
|
112
|
+
([docs/canary.md](docs/canary.md)) and patches regressions, but zero-flag is a
|
|
113
|
+
snapshot, not a guarantee.
|
|
114
|
+
- **No CAPTCHA solving.** The recovery chain *detects* CAPTCHAs and surfaces them to
|
|
115
|
+
the operator dashboard for manual intervention. It does not call solving services.
|
|
116
|
+
If you need solver integration, build a `BasePlugin` that calls your provider and
|
|
117
|
+
drops the cookie back into the session.
|
|
118
|
+
- **E2E tests against live protected sites are opt-in.** The default CI runs
|
|
119
|
+
contract + mocked integration tests. Live-site E2E (`RUN_E2E_ANTI_BLOCK=1`) is
|
|
120
|
+
flaky by nature and skipped on PRs.
|
|
121
|
+
- **Login credentials are not shipped.** Examples that touch authenticated endpoints
|
|
122
|
+
stop at the search/listing stage.
|
|
88
123
|
|
|
89
124
|
---
|
|
90
125
|
|
|
@@ -136,13 +171,15 @@ Instead of launching a new Chromium, you can attach to a Chrome you already
|
|
|
136
171
|
have running with `--remote-debugging-port=9222`:
|
|
137
172
|
|
|
138
173
|
```python
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
174
|
+
# Attach mode: use a fresh instance (async-with auto-launches a new browser first).
|
|
175
|
+
browser = AgentBrowser(session_name="attached")
|
|
176
|
+
await browser.attach_over_cdp(
|
|
177
|
+
"http://127.0.0.1:9222", # or the Windows host IP from WSL
|
|
178
|
+
new_context=True, # don't disturb the user's tabs
|
|
179
|
+
)
|
|
180
|
+
await browser.safe_goto("https://bot.sannysoft.com")
|
|
181
|
+
# safe actions + MCP scrape now operational on attached; close() leaves external browser running.
|
|
182
|
+
await browser.close()
|
|
146
183
|
```
|
|
147
184
|
|
|
148
185
|
See [docs/ATTACH_OVER_CDP.md](docs/ATTACH_OVER_CDP.md) for the WSL→Windows
|
|
@@ -151,11 +188,28 @@ degradation matrix (init-script stealth still applies; TLS/JA3 does not).
|
|
|
151
188
|
|
|
152
189
|
---
|
|
153
190
|
|
|
191
|
+
## Install from source
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
git clone https://github.com/shanewas/agentic-stealth-browser.git
|
|
195
|
+
cd agentic-stealth-browser
|
|
196
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
197
|
+
pip install -e ".[dev]"
|
|
198
|
+
playwright install chromium
|
|
199
|
+
pytest tests/ -q
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The dev extras pull in `pytest`, `pytest-asyncio`, `ruff`, and the test fixture
|
|
203
|
+
deps. The full suite takes ~2 minutes on a warm cache; the default run skips
|
|
204
|
+
live E2E (`RUN_E2E_ANTI_BLOCK=1` to enable).
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
154
208
|
## Key Features
|
|
155
209
|
|
|
156
210
|
| Feature | What It Does |
|
|
157
211
|
|---|---|
|
|
158
|
-
| **TLS Fingerprinting** | JA3/JA4
|
|
212
|
+
| **TLS Fingerprinting** | Region client-hello profiles (JA3/JA4 surface); attach mode degrades (process-level) |
|
|
159
213
|
| **Human Behavior** | Mouse wobble, typing mistakes, fatigue, distraction |
|
|
160
214
|
| **Auto Recovery** | Block detection → proxy/session rotation → retry |
|
|
161
215
|
| **Account Warming** | 14-day gradual ramp-up for new accounts |
|
|
@@ -170,12 +224,17 @@ degradation matrix (init-script stealth still applies; TLS/JA3 does not).
|
|
|
170
224
|
|
|
171
225
|
---
|
|
172
226
|
|
|
173
|
-
## New in v2.
|
|
227
|
+
## New in v2.5.0
|
|
174
228
|
|
|
175
|
-
- **
|
|
176
|
-
-
|
|
177
|
-
- **
|
|
178
|
-
|
|
229
|
+
- **BackendAdapter protocol** — pluggable execution backends (M0–M4 shipped)
|
|
230
|
+
across CDP-bridge, playwright-mcp, and agentic-stealth-mcp
|
|
231
|
+
- **Real dashboard backends** — the Hermes dashboard now wires a thin shim over
|
|
232
|
+
the adapter protocol, so the same UI drives all three backends
|
|
233
|
+
- **Attach-mode hardening** — adopted tabs are preserved on `close()`; bad
|
|
234
|
+
context/stealth installs roll back cleanly; `human`/`scraper`/`recovery`
|
|
235
|
+
initialized for attach
|
|
236
|
+
- **CLI `status`** — added `--headless` and `--session` flags for headless
|
|
237
|
+
operator checks against a named session
|
|
179
238
|
|
|
180
239
|
See [CHANGELOG.md](CHANGELOG.md) for the full release history.
|
|
181
240
|
|
|
@@ -190,6 +249,8 @@ See [CHANGELOG.md](CHANGELOG.md) for the full release history.
|
|
|
190
249
|
- **[Plugins](plugins/)** — lifecycle hooks for custom behavior
|
|
191
250
|
- **[VPS Deployment](scripts/setup_rbb.sh)** — systemd, Caddy reverse proxy, Cloudflare Tunnel patterns
|
|
192
251
|
- **[Migration v1 → v2](scripts/migrate_v1_to_v2.py)** — deprecation shims, migration guide, script
|
|
252
|
+
- **[Documentation index](docs/README.md)** — full docs/ tree: attach-over-CDP, canary, plans, analysis
|
|
253
|
+
- **[Examples](examples/recipes/)** — runnable recipes for Cloudflare, LinkedIn, Amazon
|
|
193
254
|
|
|
194
255
|
Additional references: [CHANGELOG.md](CHANGELOG.md) · [Workflow Library](workflows/library/) · [Migration Guide](scripts/migrate_v1_to_v2.py)
|
|
195
256
|
|
|
@@ -206,7 +267,9 @@ Additional references: [CHANGELOG.md](CHANGELOG.md) · [Workflow Library](workfl
|
|
|
206
267
|
├── production/ MCP server, SDK, orchestrator, security, profiler
|
|
207
268
|
├── plugins/ Plugin system with template
|
|
208
269
|
├── scripts/ Migration, evaluation, benchmarking
|
|
209
|
-
|
|
270
|
+
├── docs/ Attach-over-CDP, canary, plans, analysis
|
|
271
|
+
├── examples/ Runnable recipes (Cloudflare, LinkedIn, Amazon)
|
|
272
|
+
└── tests/ Contract + integration tests (live E2E opt-in)
|
|
210
273
|
```
|
|
211
274
|
|
|
212
275
|
## License
|