superbrowser-sdk 2.7.0__tar.gz → 2.9.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.
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/CHANGELOG.md +56 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/PKG-INFO +1 -1
- superbrowser_sdk-2.9.0/docs/design/mcp_tool_metadata.md +199 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/mcp.md +23 -5
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/pyproject.toml +1 -1
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/__init__.py +1 -1
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/facade.py +42 -2
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/controller.py +114 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/mcp_server.py +202 -6
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_controller_rebinding.py +3 -2
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_diagnostics.py +2 -2
- superbrowser_sdk-2.9.0/tests/test_mcp_interaction.py +246 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_navigation.py +8 -8
- superbrowser_sdk-2.9.0/tests/test_mcp_observe_targets.py +329 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_server.py +5 -4
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.env.example +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/adversarial-v3.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/adversarial.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/benchmark.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/dco.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/e2e.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/publish.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/smoke.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/stress.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.github/workflows/test.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.gitignore +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/.pre-commit-config.yaml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/CONTRIBUTING.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/Dockerfile +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/LICENSE +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/README.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/Super-Browser.png +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/benchmarks/fixtures/behavioral.html +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/benchmarks/fixtures/dom-heavy.html +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/benchmarks/fixtures/form.html +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/benchmarks/fixtures/simple.html +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/benchmarks/v1.11.0-baseline-patchright.json +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/benchmarks/v1.11.0-baseline-patchright.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docker-compose.yml +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/agent-reliability.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/aiv/AIV_FRAMEWORK_v5.3.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/anti-detection-ejecta.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/api-ergonomics-audit.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/api-reference.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/api-stability.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/architecture.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/behavioral-synthesis.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/browser-networking.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/cloak-integration.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/consistency-engine.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/design/inspect_redaction.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/discovery/DISCOVERY-REPORT.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/error-catalog.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/fingerprint-scoring.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/fingerprint-validation.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/gap-analysis.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/human-behavior.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/memory.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/migration/v1-to-v2.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/migration/v1.8-to-v1.9.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/operating-doctrine.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/platform-abstraction.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/plugins.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/quickstart.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/recording.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/rfcs/README.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/rfcs/v2-decomposition.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/rfcs/v2-track-a-api-simplification.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/rfcs/v2-track-b-network-stealth.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/rfcs/v2-track-c-behavioral-realism.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/rfcs/v2-track-d-challenge-infrastructure.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/rfcs/v2-track-e-e2e-harness.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/stealth-coverage.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/docs/stealth-evidence.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/backend_selection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/basic_usage.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/budget_tracking.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/cloak_stealth.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/error_handling.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/fingerprint_scan.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/human_behavior.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/multi_tab_workflow.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/session_persistence.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/examples/stealth_mode.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/adversarial_run.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/agent_efficiency_benchmark.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/browser_benchmark.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/e2e_trend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/run_stealth_gauntlet.sh +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/smoke_published.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/stress_real_world.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/validate_e2e_report.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/scripts/verify_release_artifact.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/__main__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/debug.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/delegator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/diagnostics.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/llm/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/llm/anthropic_client.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/llm/browser_transport.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/llm/budget_aware.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/llm/factory.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/llm/openai_client.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/llm/protocol.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/loop.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/loop_detector.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/plugins.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/registry.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/router.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/structured_logging.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/agent/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/bezier.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/dwell.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/fitts.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/gauss.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/keyboard.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/mouse.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/navigation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/orchestrator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/prng.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/qwerty.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/scroll.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/session_seed.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/behavioral/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/backends/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/backends/cdp_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/backends/patchright_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/backends/playwright_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/backends/selenium_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/cdp.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/cloak_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/cloud.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/discovery.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/engine.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/fetch.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/injectors/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/injectors/bidi_injector.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/injectors/cdp_injector.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/injectors/page_injector.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/page.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/session.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/shutdown.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/browser/tabs.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/cascade.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/client.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/compressor.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/cost_estimator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/credential_pool.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/governor.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/budget/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/cli/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/cli/commands.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/cli/interactive.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/cli/script.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/events/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/events/bus.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/events/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/cache.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/decorator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/presets.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/recovery.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/snapshot.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/vision.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/memory/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/memory/integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/memory/store.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/memory/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/plugins/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/plugins/decorators.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/plugins/hooks.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/py.typed +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recording/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recording/persistence.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recording/recorder.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recording/replayer.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recording/report.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recording/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/checkpoint.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/classifier.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/coordinator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/event_bus.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/format_validator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/reflection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/retry_tracker.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/session_recovery.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/recovery/watchdogs.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/results/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/results/output.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/results/typed.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/results/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/results/validation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/action_redaction.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/approval.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/credential_vault.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/domain_filter.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/gate.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/injection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/manager.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/policy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/redactor.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/security/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/session/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/session/proxy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/skills/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/skills/activation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/skills/markdown.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/skills/registry.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/skills/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/action_policy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/captcha.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/challenges/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/challenges/cache.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/challenges/pow.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/challenges/turnstile.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/dag.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/derive.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/errors.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/inject.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/inject_delivery.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/matrix.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/prng.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rule.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/audio.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/behavior.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/fonts.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/gpu.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/locale.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/navigator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/screen.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/consistency/rules/user_agent.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/diagnostics.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/audio.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/browser_apis.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/canvas.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/registry.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/timing.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ejecta/webrtc.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/fingerprint_scanner.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/fingerprint_score.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/headers.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/human.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/human_config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/ip_reputation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/manager.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/profiles/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/profiles/data/linux-chrome-stable.json +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/profiles/data/macos-chrome-stable.json +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/profiles/data/macos-m4-chrome-stable.json +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/profiles/data/windows-chrome-stable.json +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/profiles/host_detect.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/profiles/schema.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/proxy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/proxy_pool.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/report.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/scoring.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/tls_baselines.json +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/tls_fingerprint.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/user_agent_pool.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/validation/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/validation/checks.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/validation/harness.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/validation/report.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/stealth/validation/suite.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/testing.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/tracing/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/tracing/cost_analytics.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/tracing/flow_logger.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/tracing/middleware.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/tracing/session_db.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/tracing/sinks.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/tracing/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/verification/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/verification/ax_diff.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/verification/hasher.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/verification/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/verification/verifier.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/cache.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/controller.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/coords.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/factory.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/ocr.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/providers.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/vision/types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/stress/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/stress/server.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/controlled_server.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/report.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/scoring.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/targets.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/test_controlled_server.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/test_targets_unit.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/test_tier1_scanners.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/test_tier2_vendors.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial/test_tier3_controlled.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/README.md +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/backends.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/behavioral_telemetry.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/core.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/engines/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/engines/scoring.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/harness.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/reporters/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/reporters/history.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/reporters/json_reporter.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/reporters/markdown_reporter.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/server.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/automation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/behavioral.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/controlled.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/ejector.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/external.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/fingerprint.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/adversarial3/vectors/network.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/pytest.ini +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/run.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_backends.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_behavioral_telemetry.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_behavioral_telemetry_smoke.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_behavioral_vectors.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_core.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_external.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_harness_smoke.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_header_ordering.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_reporters.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_scoring.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_server.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_superbrowser_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/adversarial_v3/tests/test_vectors.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_01_example_nav.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_02_google_search.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_03_github_login.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_04_amazon_search.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_05_google_forms.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_06_google_flights.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_07_wikipedia_extract.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_08_reddit_spa.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_09_form_complex.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/discovery/test_task_10_signup_flow.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_behavioral_realism.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_challenge_detection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_interaction.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_live_navigation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_multi_tab.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_navigation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_session_persistence.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e/test_stealth_overhead.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/e2e_v1_3_journey.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_config_composition.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_engine_backends.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_error_paths.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_facade_smoke.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_full_lifecycle.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_multi_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_performance_smoke.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_playwright_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_public_api.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_session_persistence.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_stealth_abstraction.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v1100_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v150_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v160_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v170_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v180_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v190_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v191_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v192_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v193_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v194_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v195_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v1_3_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/integration/test_v1_4_features.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/pattern_validation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/conftest.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/test_chrome_runtime.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/test_cli_switches.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/test_headless_indicators.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/test_live_sites.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/test_runtime_enable.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/test_tls_fingerprint.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/stealth_detection/test_webdriver.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_action_timeout.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_browser_transport.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_debug_mode.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_default_tooling.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_delegator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_error_screenshots.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_facade.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_facade_security.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_facade_security_control.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_facade_security_file_tab.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_facade_security_network.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_facade_security_session.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_fail_fast.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_llm.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_llm_budget.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_llm_production.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_llm_streaming.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_loop.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_loop_detector.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_prompt_isolation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_registry.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_retry_budget.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_streaming.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_structured_logging.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_tab_cap.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_task_02.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_agent/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/test_behavioral.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/test_dwell.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/test_hardening.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/test_human_config_dwell.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/test_navigation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/test_orchestrator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_behavioral/test_session_seed.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_benchmark/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_benchmark/test_efficiency.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_benchmarks/test_browser_benchmark.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_benchmarks/test_stress_real_world.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_cdp.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_cdp_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_cloak_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_cloak_docs.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_cloak_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_discovery.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_engine_protocol.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_fetch.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_injectors.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_page.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_patchright_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_playwright_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_selenium_backend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_session.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_browser/test_shutdown.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_cascade.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_cascade_governor.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_circuit_breaker.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_client.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_compressor.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_cost_estimator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_credential_pool.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_governor.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_budget/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_cli/test_interactive.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_cli/test_script.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_cli/test_stealth_check.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_cli/test_stealth_validate.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_cli/test_unified_cli.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_diagnostics.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_e2e/test_report_schema.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_e2e/test_trend.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_audio.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_batch37_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_batch38_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_browser_apis.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_canvas.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_timing.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_ejecta/test_webrtc.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_events/test_event_bus.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_events/test_lifecycle_hooks.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_governance_docs.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_cache.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_controller.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_decorator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_injection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_page_change.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_presets.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_recovery.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_snapshot.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_interaction/test_vision.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_entrypoint.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_permissions.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_redaction.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_server_smoke.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_write_tools.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_mcp_write_tools_wave2.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_memory/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_memory/test_cli_config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_memory/test_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_memory/test_store.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recording/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recording/test_persistence.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recording/test_recorder.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recording/test_replayer.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_checkpoint.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_classifier.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_coordinator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_event_bus.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_format_validator.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_reflection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_retry_tracker.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_session_recovery.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_recovery/test_watchdogs.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_release/test_naming_consistency.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_release/test_smoke_published.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_release/test_verify_artifact.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_results/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_results/test_batch40_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_results/test_categories.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_results/test_output.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_results/test_typed.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_results/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_results/test_validation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_runtime_correctness/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_runtime_correctness/test_runtime_fixes.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_approval.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_credential_vault.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_domain_filter.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_injection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_manager.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_policy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_redaction_pipeline.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_redactor.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_security/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_session/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_session/test_locale.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_session/test_proxy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_skills/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_skills/test_activation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_skills/test_integration.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_skills/test_markdown.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_skills/test_registry.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_skills/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_action_policy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_captcha.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_captcha_resolution.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_challenge_cache.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_challenge_config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_consistency/test_consistency.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_consistency_inject.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_diagnostics.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_e2e_lifecycle.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_e2e_reporting.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_fingerprint_scanner.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_fingerprint_score.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_headers.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_human.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_human_behavior_v2.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_ip_reputation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_kasada_detection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_manager.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_network_stealth_config.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_profiles.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_proxy.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_proxy_pool.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_stealth_bridge.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_tls_fingerprint.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_turnstile_detection.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_user_agent_pool.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_stealth/test_validation.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_tracing/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_tracing/test_cost_analytics.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_tracing/test_flow_logger.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_tracing/test_middleware.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_tracing/test_session_db.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_tracing/test_sinks.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_tracing/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_verification/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_verification/test_ax_diff.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_verification/test_hasher.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_verification/test_types.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_verification/test_verifier.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/__init__.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/test_cache.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/test_controller.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/test_coords.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/test_factory.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/test_ocr.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/test_providers.py +0 -0
- {superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/tests/test_vision/test_types.py +0 -0
|
@@ -5,6 +5,62 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.9.0] — 2026-06-27
|
|
9
|
+
|
|
10
|
+
### Added — MCP observe actionable targets
|
|
11
|
+
|
|
12
|
+
`observe` now returns a `targets` array of actionable element references
|
|
13
|
+
extracted from the accessibility snapshot. Each target includes:
|
|
14
|
+
|
|
15
|
+
- `target` — a ref string (e.g. `@e0`) usable as the `target` argument for
|
|
16
|
+
coordinate-tier action tools: `click`, `fill`, `type_text`, `hover`,
|
|
17
|
+
`select_option`. Checkbox/radio targets map to `click` (toggle-like) because
|
|
18
|
+
`check`/`uncheck` are selector-tier only and cannot resolve `@refs`.
|
|
19
|
+
- `role` — the AX role (button, textbox, checkbox, combobox, link, etc.)
|
|
20
|
+
- `name` — the accessible name (subject to inspect-output redaction)
|
|
21
|
+
- `action_hint` — recommended action for the role (`click`, `fill`,
|
|
22
|
+
select_option)
|
|
23
|
+
|
|
24
|
+
Targets are capped at 50 interactive, non-disabled elements.
|
|
25
|
+
`targets_truncated` indicates when more exist. This closes the gap where
|
|
26
|
+
agents had to guess CSS selectors — they can now go `observe → action`
|
|
27
|
+
deterministically using the refs returned by `observe`.
|
|
28
|
+
|
|
29
|
+
### Documentation — MCP tool metadata design note (P4)
|
|
30
|
+
|
|
31
|
+
Added `docs/design/mcp_tool_metadata.md` — a design note analyzing whether
|
|
32
|
+
MCP tool schemas, tiers, validation, and docs should be unified onto the
|
|
33
|
+
existing `ToolDefinition` registry. **Decision: defer full unification.** The
|
|
34
|
+
current `ToolDefinition` cannot express MCP-specific metadata (tiers, enums,
|
|
35
|
+
ranges, validation hooks, bool-as-int rejection) without lossy flattening. Keep
|
|
36
|
+
`mcp_server.py` as the MCP source of truth until tool count or a production
|
|
37
|
+
mismatch justifies change. Trigger conditions and three future options
|
|
38
|
+
documented.
|
|
39
|
+
|
|
40
|
+
## [2.8.0] — 2026-06-26
|
|
41
|
+
|
|
42
|
+
### Added — MCP interaction tools (P3.1)
|
|
43
|
+
|
|
44
|
+
Six new action-tier MCP tools for form and element interaction:
|
|
45
|
+
|
|
46
|
+
- `hover` — hover over an element (controller-backed, selector/coordinate/vision cascade)
|
|
47
|
+
- `select_option` — select an option in a `<select>` element (maps to controller `select`, supports `by`: text/value/label)
|
|
48
|
+
- `check` — check a checkbox or radio button (new controller method + cascade)
|
|
49
|
+
- `uncheck` — uncheck a checkbox (new controller method + cascade)
|
|
50
|
+
- `focus` — focus an element (new controller method, selector-tier only)
|
|
51
|
+
- `type_text` — type text character-by-character (per-keystroke), triggering JS key listeners. Unlike `fill` which sets the value atomically. Supports `delay_ms` (0–1000). (new controller method)
|
|
52
|
+
|
|
53
|
+
All six are action-tier: require `--allow-actions`, consume the action budget,
|
|
54
|
+
pass through `SecurityManager` + audit, and are absent from the default
|
|
55
|
+
advertised surface.
|
|
56
|
+
|
|
57
|
+
- Default advertised tools: remains 17
|
|
58
|
+
- Action-mode advertised tools: 23 → 29
|
|
59
|
+
|
|
60
|
+
New controller primitives (`check`, `uncheck`, `focus`, `type_text`) added to
|
|
61
|
+
`MultimodalController` with `@agent_action` decorators and `FrameInteractionTarget`
|
|
62
|
+
adapters. Registered in the facade's builtin-tool loop.
|
|
63
|
+
|
|
8
64
|
## [2.7.0] — 2026-06-26
|
|
9
65
|
|
|
10
66
|
### Added — MCP reload and history navigation tools (P3.0B)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: superbrowser-sdk
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: Anti-detection agent browser SDK — stealth, budget governance, security guardrails, and structured error recovery behind one async facade
|
|
5
5
|
Project-URL: Homepage, https://github.com/Octo-Lex/Super-Browser
|
|
6
6
|
Project-URL: Documentation, https://github.com/Octo-Lex/Super-Browser#readme
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Design Note: MCP Tool Metadata Unification
|
|
2
|
+
|
|
3
|
+
> **Status:** Design note. No implementation.
|
|
4
|
+
> **Decision:** Defer full unification. Document the metadata contract; keep
|
|
5
|
+
> `mcp_server.py` as the MCP source of truth until pressure justifies change.
|
|
6
|
+
> **Date:** 2026-06-26
|
|
7
|
+
|
|
8
|
+
## Core question
|
|
9
|
+
|
|
10
|
+
Should Super-Browser extend `ToolDefinition` to become the single source of
|
|
11
|
+
truth for MCP schemas, tiers, validation, and docs — or should MCP remain
|
|
12
|
+
hand-curated until there is stronger pressure?
|
|
13
|
+
|
|
14
|
+
## Current state (v2.8.0)
|
|
15
|
+
|
|
16
|
+
The MCP server advertises **29 tools** in action mode (17 default). Tool
|
|
17
|
+
metadata is maintained in three parallel places:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
1. ToolRegistry / ToolDefinition / ToolParameter (agent-loop path)
|
|
21
|
+
- src/super_browser/agent/registry.py
|
|
22
|
+
- Typed specs, handlers, JSON schemas, toolsets, security_level
|
|
23
|
+
- Used by AgentLoop for the embedded act() path
|
|
24
|
+
|
|
25
|
+
2. MCP types.Tool definitions + _tool_* handlers (MCP path)
|
|
26
|
+
- src/super_browser/mcp_server.py
|
|
27
|
+
- Hand-maintained lists: PHASE1_TOOLS, NAVIGATION_AUX_TOOLS,
|
|
28
|
+
DIAGNOSTICS_TOOLS, INTERACTION_TOOLS, PHASE2B_TOOLS, PHASE2B_WAVE2_TOOLS
|
|
29
|
+
- Handlers wired by name-string convention: getattr(self, f"_tool_{name}")
|
|
30
|
+
|
|
31
|
+
3. MCP tier names + validation + authorization path (MCP path)
|
|
32
|
+
- INSPECT_TOOL_NAMES, NAVIGATION_TOOL_NAMES, ACTION_TOOL_NAMES frozensets
|
|
33
|
+
- Tool-tier list membership determines advertised/default/action behavior
|
|
34
|
+
- _validate_navigation_args / _validate_action_args (hand-written Python)
|
|
35
|
+
- MCPAuthorizer / SecurityManager path for action authorization
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
These three sources are synchronized manually. Tests assert advertised counts
|
|
39
|
+
and tier membership, but there is no compile-time guarantee they agree.
|
|
40
|
+
|
|
41
|
+
## Problem
|
|
42
|
+
|
|
43
|
+
Duplication is growing. Each new MCP tool requires:
|
|
44
|
+
|
|
45
|
+
- A `types.Tool` definition (schema, description)
|
|
46
|
+
- A `_tool_*` handler method
|
|
47
|
+
- An entry in the right `*_TOOLS` list (which determines tier membership)
|
|
48
|
+
- An entry in `_validate_action_args` or `_validate_navigation_args` (hand-written validation)
|
|
49
|
+
- An entry in the `ACTION_TOOL_NAMES` / `NAVIGATION_TOOL_NAMES` frozenset
|
|
50
|
+
- Updates to count assertions across 4+ test files
|
|
51
|
+
- Updates to `docs/mcp.md` (tool table + counts)
|
|
52
|
+
- Updates to `CHANGELOG.md`
|
|
53
|
+
|
|
54
|
+
That is 8 touch points per tool. With 29 tools now and P5/P6 work still ahead,
|
|
55
|
+
the maintenance surface is real.
|
|
56
|
+
|
|
57
|
+
## Why current ToolDefinition cannot serve as MCP source of truth
|
|
58
|
+
|
|
59
|
+
Fact-checked against `src/super_browser/agent/registry.py` (lines 17-63):
|
|
60
|
+
|
|
61
|
+
### 1. Schema expressiveness is too flat
|
|
62
|
+
|
|
63
|
+
`ToolDefinition.to_json_schema()` produces a flat type system:
|
|
64
|
+
`str→string, int→integer, float→number, bool→boolean`. It cannot express:
|
|
65
|
+
|
|
66
|
+
- **Enums** — used heavily: `scroll.direction`, `wait_for.load_state`,
|
|
67
|
+
`select_option.by`, `reload.wait_until`
|
|
68
|
+
- **Defaults** — MCP uses `"default": false`, `"default": 10000`;
|
|
69
|
+
`ToolParameter` stores a default but `to_json_schema()` never emits it
|
|
70
|
+
- **Numeric ranges** — `wait_for.timeout_ms` (100–60000),
|
|
71
|
+
`type_text.delay_ms` (0–1000)
|
|
72
|
+
- **Bool-as-int rejection** — MCP validation explicitly rejects `bool` where
|
|
73
|
+
`int` is expected; `ToolParameter` has no concept of this
|
|
74
|
+
- **Nested objects / arrays** — MCP `inputSchema.properties` can nest
|
|
75
|
+
|
|
76
|
+
### 2. Tier metadata is a different axis
|
|
77
|
+
|
|
78
|
+
`ToolDefinition.security_level` takes values `safe`/`sensitive`/`dangerous`
|
|
79
|
+
(a risk scale). MCP tiers are `inspect`/`navigation`/`action` (permission
|
|
80
|
+
buckets, assigned by list membership). There is no automatic mapping:
|
|
81
|
+
|
|
82
|
+
- `navigate` is `sensitive` but navigation-tier (default-allowed)
|
|
83
|
+
- `scroll` is `safe` but action-tier (gated)
|
|
84
|
+
- `screenshot` is `sensitive` but inspect-tier (no security check)
|
|
85
|
+
|
|
86
|
+
`ToolDefinition` has no `tier` field. Its `toolsets` field is a grouping
|
|
87
|
+
concept unrelated to MCP permission tiers.
|
|
88
|
+
|
|
89
|
+
### 3. Validation hooks are hand-written Python
|
|
90
|
+
|
|
91
|
+
MCP argument validation (`_validate_navigation_args`,
|
|
92
|
+
`_validate_action_args`) contains logic that no schema can express:
|
|
93
|
+
non-empty string checks, bool-as-int rejection, range bounds, exactly-one-
|
|
94
|
+
condition constraints (`wait_for`). This logic cannot be generated from any
|
|
95
|
+
data structure — it requires executable validation hooks.
|
|
96
|
+
|
|
97
|
+
### 4. Handler dispatch is name-string convention
|
|
98
|
+
|
|
99
|
+
MCP dispatches via `getattr(self, f"_tool_{name}")`. This is a runtime
|
|
100
|
+
convention with no type safety. `ToolDefinition.handler` is a callable
|
|
101
|
+
reference, but the MCP path doesn't use it — it uses its own dispatch table.
|
|
102
|
+
|
|
103
|
+
## What MCP metadata would need (the full contract)
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
Per-tool metadata required:
|
|
107
|
+
- tool name (str)
|
|
108
|
+
- tier: inspect | navigation | action | high_risk
|
|
109
|
+
- advertised_by_default: bool (derived from tier)
|
|
110
|
+
- security_level: safe | sensitive | dangerous
|
|
111
|
+
- action_budget: consumes | does_not_consume
|
|
112
|
+
- input schema:
|
|
113
|
+
- parameter name
|
|
114
|
+
- type (str, int, bool, str-enum, ...)
|
|
115
|
+
- required: bool
|
|
116
|
+
- default value
|
|
117
|
+
- enum values (where applicable)
|
|
118
|
+
- numeric range (min, max)
|
|
119
|
+
- reject_bool_as_int: bool
|
|
120
|
+
- validation hook: callable(args) -> error | None
|
|
121
|
+
- handler binding: callable or name convention
|
|
122
|
+
- description (for MCP tool listing)
|
|
123
|
+
- redaction policy: which output fields to redact, text vs URL
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This is substantially richer than what `ToolDefinition` carries today.
|
|
127
|
+
|
|
128
|
+
## Decision: defer full unification
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
Do not implement automatic MCP schema generation now.
|
|
132
|
+
|
|
133
|
+
Reasons:
|
|
134
|
+
1. Current ToolDefinition cannot express MCP metadata without lossy flattening.
|
|
135
|
+
2. Forcing MCP schemas through it would damage validation, enums, ranges.
|
|
136
|
+
3. The maintenance pain (8 touch points per tool) is real but manageable
|
|
137
|
+
at 29 tools.
|
|
138
|
+
4. A partial generator that can't express tier/validation/security
|
|
139
|
+
faithfully is worse than hand-curated — it would create a false sense
|
|
140
|
+
of single-source-of-truth while silently diverging.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## What to do instead
|
|
144
|
+
|
|
145
|
+
### Now (no code change)
|
|
146
|
+
|
|
147
|
+
Keep `mcp_server.py` as the MCP source of truth. Document this design note
|
|
148
|
+
as the contract for what a future unification would require.
|
|
149
|
+
|
|
150
|
+
### Trigger conditions for revisiting
|
|
151
|
+
|
|
152
|
+
Re-evaluate when any of these become true:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
1. MCP tool count exceeds ~40 (currently 29)
|
|
156
|
+
2. A tool is added with the wrong tier and isn't caught until production
|
|
157
|
+
3. Validation logic is duplicated between MCP and SDK paths
|
|
158
|
+
4. A third consumer (e.g. external-agent API) needs the same metadata
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Future options (when triggered)
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
Option A — MCPToolDefinition wrapper:
|
|
165
|
+
A new dataclass that wraps ToolDefinition and adds MCP-specific fields
|
|
166
|
+
(tier, advertised_by_default, validation_hook, redaction_policy).
|
|
167
|
+
Pro: doesn't pollute the SDK registry.
|
|
168
|
+
Con: still two definitions per tool.
|
|
169
|
+
|
|
170
|
+
Option B — Extend ToolDefinition:
|
|
171
|
+
Add tier, enum_constraints, defaults, ranges, validation_hook fields.
|
|
172
|
+
Pro: true single source of truth.
|
|
173
|
+
Con: makes the SDK registry awkward for non-MCP consumers; schema migration.
|
|
174
|
+
|
|
175
|
+
Option C — Generate MCP from a new tool-spec module:
|
|
176
|
+
A dedicated mcp_tools.py that defines tool specs with full metadata,
|
|
177
|
+
generates types.Tool objects, validation functions, and docs entries.
|
|
178
|
+
Pro: MCP owns its own metadata; no SDK pollution.
|
|
179
|
+
Con: doesn't unify with the SDK registry (but that may be acceptable).
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The design note recommends **Option C** if/when triggered — it keeps MCP
|
|
183
|
+
and SDK concerns separate while reducing MCP's internal duplication.
|
|
184
|
+
|
|
185
|
+
## Comparison to existing inspect-redaction design
|
|
186
|
+
|
|
187
|
+
The P2.3 redaction design (`docs/design/inspect_redaction.md`) took a
|
|
188
|
+
similar approach: document the boundary, reuse existing machinery, defer
|
|
189
|
+
per-tool overrides. This note follows the same pattern for tool metadata.
|
|
190
|
+
|
|
191
|
+
## Summary
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
Problem: 8 touch points per MCP tool; metadata in 3+ places.
|
|
195
|
+
Root cause: ToolDefinition is too flat for MCP's needs.
|
|
196
|
+
Decision: Defer unification. Keep hand-curated MCP.
|
|
197
|
+
Trigger: ~40 tools, or a tier-mismatch production incident.
|
|
198
|
+
Preferred future path: Option C (dedicated MCP tool-spec module).
|
|
199
|
+
```
|
|
@@ -7,7 +7,7 @@ scripting Python.
|
|
|
7
7
|
|
|
8
8
|
The stdio server advertises **seventeen tools by default** (six inspect + five
|
|
9
9
|
diagnostics + six navigation) — enough to read a URL end-to-end and explain
|
|
10
|
-
why a read failed. When action mode is enabled, it advertises **
|
|
10
|
+
why a read failed. When action mode is enabled, it advertises **twelve additional
|
|
11
11
|
action tools**; every action call is checked by
|
|
12
12
|
`MCPSessionPolicy` and `SecurityManager` before it can reach the browser.
|
|
13
13
|
|
|
@@ -32,7 +32,7 @@ Either of:
|
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
superbrowser-mcp # default: 17 tools (inspect + diagnostics + navigation)
|
|
35
|
-
superbrowser-mcp --allow-actions #
|
|
35
|
+
superbrowser-mcp --allow-actions # 29 tools (adds the action tier)
|
|
36
36
|
python -m super_browser.mcp_server
|
|
37
37
|
```
|
|
38
38
|
|
|
@@ -115,7 +115,7 @@ advertised; the third requires action mode; the fourth is not implemented.
|
|
|
115
115
|
|---|---|---|---|
|
|
116
116
|
| `browser_status` | none | Runtime status (running, backend). | No |
|
|
117
117
|
| `current_url` | none | Current URL, or a structured "not started" state. | No |
|
|
118
|
-
| `observe` | none | Page state: URL, title, interactive/total element counts. | Yes |
|
|
118
|
+
| `observe` | none | Page state: URL, title, interactive/total element counts, and a `targets` array of actionable element references (capped at 50). Each target includes `target` (a ref like `@e0`, usable as the `target` argument for coordinate-tier action tools: `click`, `fill`, `type_text`, `hover`, `select_option`), `role`, `name`, and `action_hint`. | Yes |
|
|
119
119
|
| `extract_text` | `query` (required), `selector` (optional) | Text content, optionally scoped to a CSS selector. | Yes |
|
|
120
120
|
| `screenshot` | `full_page` (optional, default `false`) | Base64 PNG of the viewport or full page. | Yes |
|
|
121
121
|
| `list_tabs` | none | Snapshot of open tabs. | Yes |
|
|
@@ -162,7 +162,17 @@ results; compound waits can be added later as an explicit AND mode).
|
|
|
162
162
|
navigate → wait_for → observe / extract_text / screenshot
|
|
163
163
|
```
|
|
164
164
|
|
|
165
|
-
This is the default-mode loop an agent uses to read a page.
|
|
165
|
+
This is the default-mode loop an agent uses to read a page. `observe` returns
|
|
166
|
+
actionable targets (`@e0` refs) that can be passed directly as the `target`
|
|
167
|
+
argument to coordinate-tier action tools (`click`, `fill`, `type_text`,
|
|
168
|
+
`hover`, `select_option`):
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
navigate → wait_for → observe → click(target="@e0")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The `targets` array is capped at 50; `targets_truncated` indicates whether more
|
|
175
|
+
interactive elements exist. Target names are subject to inspect-output redaction.
|
|
166
176
|
|
|
167
177
|
#### Debugging workflow
|
|
168
178
|
|
|
@@ -192,9 +202,17 @@ entry, no side effects.
|
|
|
192
202
|
| `fill` | `target` (required), `value` (required), `clear_first` (optional), `description` (optional) | SENSITIVE |
|
|
193
203
|
| `open_tab` | `url` (optional) | SENSITIVE — URL passed to `SecurityManager` when provided |
|
|
194
204
|
| `close_tab` | `tab_id` (required) | SENSITIVE |
|
|
205
|
+
| `hover` | `target` (required), `description` (optional) | SENSITIVE |
|
|
206
|
+
| `select_option` | `target` (required), `option` (required), `by` (optional: text/value/label), `description` (optional) | SENSITIVE |
|
|
207
|
+
| `check` | `target` (required), `description` (optional) | SENSITIVE |
|
|
208
|
+
| `uncheck` | `target` (required), `description` (optional) | SENSITIVE |
|
|
209
|
+
| `focus` | `target` (required), `description` (optional) | SENSITIVE |
|
|
210
|
+
| `type_text` | `target` (required), `text` (required), `delay_ms` (optional, 0–1000), `description` (optional) | SENSITIVE |
|
|
195
211
|
|
|
196
212
|
`fill` sends only the literal value supplied by the caller. It does not
|
|
197
|
-
retrieve, infer, store, or auto-fill credentials.
|
|
213
|
+
retrieve, infer, store, or auto-fill credentials. `type_text` types
|
|
214
|
+
character-by-character (per-keystroke), triggering JS key listeners — unlike
|
|
215
|
+
`fill` which sets the value atomically.
|
|
198
216
|
|
|
199
217
|
#### Action workflow
|
|
200
218
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "superbrowser-sdk"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.9.0"
|
|
8
8
|
description = "Anti-detection agent browser SDK — stealth, budget governance, security guardrails, and structured error recovery behind one async facade"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -6,7 +6,7 @@ from super_browser.agent.types import StreamEvent as StreamEvent # noqa: F401
|
|
|
6
6
|
from super_browser.config import Config as Config # noqa: F401
|
|
7
7
|
from super_browser.results.types import ActionResult as ActionResult # noqa: F401
|
|
8
8
|
|
|
9
|
-
__version__ = "2.
|
|
9
|
+
__version__ = "2.9.0"
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"SuperBrowser",
|
|
@@ -482,10 +482,49 @@ class SuperBrowser:
|
|
|
482
482
|
snap = await self._controller.capture_ax_snapshot()
|
|
483
483
|
interactive_count = sum(1 for n in snap.nodes.values() if n.is_interactive)
|
|
484
484
|
|
|
485
|
+
# Build actionable targets from the AX snapshot.
|
|
486
|
+
# The ref (e.g. "@e0") is directly usable as a `target` argument for
|
|
487
|
+
# click/fill/type_text/etc. — the controller's coordinate tier resolves
|
|
488
|
+
# @refs to element coordinates via the snapshot.
|
|
489
|
+
_ROLE_ACTION_MAP = {
|
|
490
|
+
"button": "click", "link": "click", "menuitem": "click",
|
|
491
|
+
"tab": "click", "treeitem": "click", "option": "click",
|
|
492
|
+
"textbox": "fill", "searchbox": "fill", "spinbutton": "fill",
|
|
493
|
+
"combobox": "select_option", "checkbox": "click", "radio": "click",
|
|
494
|
+
"slider": "fill", "switch": "click",
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
# Only include nodes whose center is resolvable (bounds present),
|
|
498
|
+
# because @refs are resolved via the coordinate tier. Nodes without
|
|
499
|
+
# bounds cannot be acted on and would produce a confusing target.
|
|
500
|
+
# Checkbox/radio map to "click" (not "check") because check/uncheck
|
|
501
|
+
# are selector-tier only and cannot resolve @refs.
|
|
502
|
+
all_interactive = [
|
|
503
|
+
n for n in snap.nodes.values()
|
|
504
|
+
if n.is_interactive and not n.disabled and n.center is not None
|
|
505
|
+
]
|
|
506
|
+
_MAX_TARGETS = 50
|
|
507
|
+
capped = all_interactive[:_MAX_TARGETS]
|
|
508
|
+
targets = [
|
|
509
|
+
{
|
|
510
|
+
"target": n.ref if n.ref.startswith("@") else f"@{n.ref}",
|
|
511
|
+
"role": n.role,
|
|
512
|
+
"name": n.name,
|
|
513
|
+
"action_hint": _ROLE_ACTION_MAP.get(n.role, "click"),
|
|
514
|
+
}
|
|
515
|
+
for n in capped
|
|
516
|
+
]
|
|
517
|
+
|
|
485
518
|
return timed_action_result(
|
|
486
519
|
ok=True,
|
|
487
520
|
start_ns=start,
|
|
488
|
-
data={
|
|
521
|
+
data={
|
|
522
|
+
"url": url, "title": title,
|
|
523
|
+
"interactive_elements": interactive_count,
|
|
524
|
+
"total_elements": len(snap.nodes),
|
|
525
|
+
"targets": targets,
|
|
526
|
+
"targets_truncated": len(all_interactive) > _MAX_TARGETS,
|
|
527
|
+
},
|
|
489
528
|
)
|
|
490
529
|
|
|
491
530
|
# -- Tab helper (CHK-07) --
|
|
@@ -1003,7 +1042,8 @@ class SuperBrowser:
|
|
|
1003
1042
|
# self._controller, the registered tools still route to the current
|
|
1004
1043
|
# controller. Raw bound methods would capture the old controller
|
|
1005
1044
|
# instance and act on a stale page after tab switches.
|
|
1006
|
-
for name in ("click", "fill", "select", "hover", "drag", "scroll", "keypress"
|
|
1045
|
+
for name in ("click", "fill", "select", "hover", "drag", "scroll", "keypress",
|
|
1046
|
+
"check", "uncheck", "focus", "type_text"):
|
|
1007
1047
|
method = getattr(self._controller, name, None)
|
|
1008
1048
|
if method is not None and self._registry.get(name) is None:
|
|
1009
1049
|
self._registry.register(self._make_controller_wrapper(name))
|
{superbrowser_sdk-2.7.0 → superbrowser_sdk-2.9.0}/src/super_browser/interaction/controller.py
RENAMED
|
@@ -81,6 +81,18 @@ class FrameInteractionTarget:
|
|
|
81
81
|
async def hover(self, selector: str) -> None:
|
|
82
82
|
await self._frame.locator(selector).hover()
|
|
83
83
|
|
|
84
|
+
async def check(self, selector: str) -> None:
|
|
85
|
+
await self._frame.locator(selector).check()
|
|
86
|
+
|
|
87
|
+
async def uncheck(self, selector: str) -> None:
|
|
88
|
+
await self._frame.locator(selector).uncheck()
|
|
89
|
+
|
|
90
|
+
async def focus(self, selector: str) -> None:
|
|
91
|
+
await self._frame.locator(selector).focus()
|
|
92
|
+
|
|
93
|
+
async def type_text(self, selector: str, text: str, *, delay: int = 0) -> None:
|
|
94
|
+
await self._frame.locator(selector).type(text, delay=delay)
|
|
95
|
+
|
|
84
96
|
async def drag_and_drop(self, source: str, target: str) -> None:
|
|
85
97
|
src = self._frame.locator(source)
|
|
86
98
|
dst = self._frame.locator(target)
|
|
@@ -328,6 +340,108 @@ class MultimodalController:
|
|
|
328
340
|
result, _ = await self._cascade("hover", target, description, t1, t2, t3)
|
|
329
341
|
return result
|
|
330
342
|
|
|
343
|
+
@agent_action(security_level="sensitive")
|
|
344
|
+
async def check(
|
|
345
|
+
self,
|
|
346
|
+
target: str,
|
|
347
|
+
*,
|
|
348
|
+
description: Optional[str] = None,
|
|
349
|
+
) -> ActionResult:
|
|
350
|
+
"""Check a checkbox or radio button.
|
|
351
|
+
|
|
352
|
+
Selector-tier only — coordinate/vision fallbacks would be toggle-like
|
|
353
|
+
(clicks that can uncheck an already-checked box), violating the
|
|
354
|
+
idempotent state-enforcing semantics implied by the tool name.
|
|
355
|
+
"""
|
|
356
|
+
|
|
357
|
+
async def t1():
|
|
358
|
+
await self._interaction_target.check(target)
|
|
359
|
+
return action_result(ok=True, data={"target": target}, method=ActionMethod.SELECTOR)
|
|
360
|
+
|
|
361
|
+
result, _ = await self._cascade("check", target, description, t1)
|
|
362
|
+
return result
|
|
363
|
+
|
|
364
|
+
@agent_action(security_level="sensitive")
|
|
365
|
+
async def uncheck(
|
|
366
|
+
self,
|
|
367
|
+
target: str,
|
|
368
|
+
*,
|
|
369
|
+
description: Optional[str] = None,
|
|
370
|
+
) -> ActionResult:
|
|
371
|
+
"""Uncheck a checkbox.
|
|
372
|
+
|
|
373
|
+
Selector-tier only — same rationale as ``check``: coordinate/vision
|
|
374
|
+
fallbacks would be toggle-like, not state-enforcing.
|
|
375
|
+
"""
|
|
376
|
+
|
|
377
|
+
async def t1():
|
|
378
|
+
await self._interaction_target.uncheck(target)
|
|
379
|
+
return action_result(ok=True, data={"target": target}, method=ActionMethod.SELECTOR)
|
|
380
|
+
|
|
381
|
+
result, _ = await self._cascade("uncheck", target, description, t1)
|
|
382
|
+
return result
|
|
383
|
+
|
|
384
|
+
@agent_action(security_level="sensitive")
|
|
385
|
+
async def focus(
|
|
386
|
+
self,
|
|
387
|
+
target: str,
|
|
388
|
+
*,
|
|
389
|
+
description: Optional[str] = None,
|
|
390
|
+
) -> ActionResult:
|
|
391
|
+
"""Focus an element."""
|
|
392
|
+
|
|
393
|
+
async def t1():
|
|
394
|
+
await self._interaction_target.focus(target)
|
|
395
|
+
return action_result(ok=True, data={"target": target}, method=ActionMethod.SELECTOR)
|
|
396
|
+
|
|
397
|
+
# Focus has no meaningful coordinate/vision fallback — a click would be
|
|
398
|
+
# a different action, not a focus. Only selector-tier.
|
|
399
|
+
result, _ = await self._cascade("focus", target, description, t1)
|
|
400
|
+
return result
|
|
401
|
+
|
|
402
|
+
@agent_action(security_level="sensitive")
|
|
403
|
+
async def type_text(
|
|
404
|
+
self,
|
|
405
|
+
target: str,
|
|
406
|
+
text: str,
|
|
407
|
+
*,
|
|
408
|
+
delay: int = 0,
|
|
409
|
+
description: Optional[str] = None,
|
|
410
|
+
) -> ActionResult:
|
|
411
|
+
"""Type text character-by-character (per-keystroke), unlike fill.
|
|
412
|
+
|
|
413
|
+
Triggers JS keydown/keypress/keyup listeners, suitable for autocomplete,
|
|
414
|
+
masked inputs, and debounce handlers.
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
async def t1():
|
|
418
|
+
await self._interaction_target.type_text(target, text, delay=delay)
|
|
419
|
+
return action_result(ok=True, data={"target": target, "text_length": len(text)}, method=ActionMethod.SELECTOR)
|
|
420
|
+
|
|
421
|
+
async def t2():
|
|
422
|
+
coords = await self._resolve_to_coordinates(target)
|
|
423
|
+
if coords is None:
|
|
424
|
+
return action_result(ok=False, error=ActionError(ErrorCategory.SELECTOR_NOT_FOUND, f"Cannot resolve '{target}'"))
|
|
425
|
+
# Click to focus, then type via CDP.
|
|
426
|
+
await self._cdp.send("Input.dispatchMouseEvent", {
|
|
427
|
+
"type": "mousePressed", "x": coords[0], "y": coords[1],
|
|
428
|
+
"button": "left", "clickCount": 1,
|
|
429
|
+
})
|
|
430
|
+
await self._cdp.send("Input.dispatchMouseEvent", {
|
|
431
|
+
"type": "mouseReleased", "x": coords[0], "y": coords[1],
|
|
432
|
+
"button": "left", "clickCount": 1,
|
|
433
|
+
})
|
|
434
|
+
for char in text:
|
|
435
|
+
await self._cdp.send("Input.dispatchKeyEvent", {
|
|
436
|
+
"type": "char", "text": char,
|
|
437
|
+
})
|
|
438
|
+
if delay:
|
|
439
|
+
await asyncio.sleep(delay / 1000)
|
|
440
|
+
return action_result(ok=True, data={"target": target, "method": "coordinate"}, method=ActionMethod.COORDINATE)
|
|
441
|
+
|
|
442
|
+
result, _ = await self._cascade("type_text", target, description, t1, t2)
|
|
443
|
+
return result
|
|
444
|
+
|
|
331
445
|
@agent_action(security_level="dangerous")
|
|
332
446
|
async def drag(
|
|
333
447
|
self,
|