Skip to content

Feat/firefox#396

Open
thalissonvs wants to merge 28 commits intomainfrom
feat/firefox
Open

Feat/firefox#396
thalissonvs wants to merge 28 commits intomainfrom
feat/firefox

Conversation

@thalissonvs
Copy link
Copy Markdown
Member

No description provided.

thalissonvs and others added 28 commits March 24, 2026 14:14
…c providers

Add LLM-based extraction support alongside the existing CSS selector strategy.
Fields with only a description (no selector) can now be extracted via LLM providers.

- Add ExtractionStrategy enum (CSS, LLM, AUTO) and LLMProvider protocol
- Add OpenAI and Anthropic built-in providers using aiohttp (no SDK dependency)
- Add clean_html utility for HTML-to-clean-HTML conversion (boilerplate removal)
- Add html_to_markdown converter with Readability-inspired heuristics
- Add tab.llm_provider and tab.extraction_strategy convenience properties
- Add validate_llm_provider for fail-fast when LLM is needed but not configured
- Add LLMExtractionFailed and LLMProviderNotConfigured exceptions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… protocol base

Move all CDP protocol definitions from protocol/ to protocol/cdp/ to
make room for the new BiDi protocol subpackage. Add initial BiDi base
types and session/browser module definitions for Firefox support.
…nection handler

Split ConnectionHandler into BaseConnectionHandler (ABC) with shared
WebSocket mechanics and CDPConnectionHandler / BiDiConnectionHandler
implementations. Extract CDP-specific event tracking from EventsManager
into CDPEventTracker and BiDiEventTracker classes.
…hromium

Rename interfaces.py to protocols.py with OptionsProtocol and
BrowserOptionsManagerProtocol using typing.Protocol instead of ABC.
Move options.py and tab.py into chromium/ subpackage. Merge
ChromiumOptionsManager into chromium/options.py. Use OptionsProtocol
in managers for dependency inversion.
Add FirefoxBrowser base class and Firefox implementation using
BiDi connection handler. Same public API as Chromium Browser with
typed command execution. Unsupported CDP-specific methods raise
UnsupportedOperation.
…ic methods

Add pydoll/protocol/types.py with protocol-agnostic types (Header,
Cookie, CookieParam, WindowBounds, BrowserVersion, DownloadBehavior,
RequestMethod). Privatize CDP-specific methods in Browser and Tab:
enable/disable domain events, get_targets, get_tab_by_target,
get_window_id_for_target, get_window_id. Update get_version to return
BrowserVersion, set_window_bounds to accept WindowBounds, remove
events_enabled from set_download_behavior. Add plan.md for unified API
migration.
Update FirefoxBrowser to use BrowserVersion, Cookie, CookieParam,
DownloadBehavior, WindowBounds from pydoll.protocol.types. Convert
between generic and BiDi-specific formats internally. Remove
CDP-specific stubs, keep get_opened_tabs as NotImplementedError
until BiDi Tab is built.
…requests

Add pydoll/protocol/events.py with Event enum and CDP/BiDi mapping.
Add InterceptedRequest for protocol-agnostic request interception.
Implement intercept_requests()/remove_intercept() in both Chrome and
Firefox browsers. Update on() to accept Event enum with auto-enable
for CDP domains. Fix BiDi Command type aliases to wrap with
CommandResponse for correct typing.
…s, and cookies

Add BiDiTab class using shared BiDi connection with context ID.
Implements go_to, refresh, close, bring_to_front, title, current_url,
page_source, take_screenshot, print_to_pdf, execute_script, cookies,
dialog handling, on/remove_callback, and network_logs. Update
FirefoxBrowser with start returning tab, get_opened_tabs, and new_tab.
Convert BiDi remote values (number, string, boolean, null, undefined,
array, object, map, set, date, regexp, bigint) to native Python types
instead of returning raw protocol dicts.
… implementation

Extract CDP-specific element finding logic into CDPFindElementsMixin.
FindElementsMixin now contains only protocol-agnostic code (find, query,
retry/timeout, selector parsing). Add WebElementProtocol in
elements/protocols.py. Move web_element.py and shadow_root.py into
elements/cdp/ subpackage. Privatize find_or_wait_element.
Implement BiDi element finding using browsingContext.locateNodes with
typed Locator variants (CssLocator, XPathLocator). BiDiWebElement uses
sharedId for element references and script.callFunction for all
interactions (click, text, visibility, etc). BiDiTab now inherits
BidiFindElementsMixin for find()/query() support.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 8, 2026

Important

Review skipped

Too many files!

This PR contains 198 files, which is 48 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 58107220-a31f-477c-90d3-3cb62fae93d6

📥 Commits

Reviewing files that changed from the base of the PR and between 07f4d9a and f07ab53.

📒 Files selected for processing (198)
  • .gitignore
  • plan.md
  • pydoll/browser/__init__.py
  • pydoll/browser/chromium/base.py
  • pydoll/browser/chromium/chrome.py
  • pydoll/browser/chromium/edge.py
  • pydoll/browser/chromium/options.py
  • pydoll/browser/chromium/tab.py
  • pydoll/browser/firefox/__init__.py
  • pydoll/browser/firefox/base.py
  • pydoll/browser/firefox/firefox.py
  • pydoll/browser/firefox/options.py
  • pydoll/browser/firefox/tab.py
  • pydoll/browser/intercepted_request.py
  • pydoll/browser/interfaces.py
  • pydoll/browser/managers/__init__.py
  • pydoll/browser/managers/browser_options_manager.py
  • pydoll/browser/managers/proxy_manager.py
  • pydoll/browser/protocols.py
  • pydoll/browser/requests/har_recorder.py
  • pydoll/browser/requests/request.py
  • pydoll/browser/requests/response.py
  • pydoll/commands/__init__.py
  • pydoll/commands/bidi/__init__.py
  • pydoll/commands/bidi/browser_commands.py
  • pydoll/commands/bidi/browsing_context_commands.py
  • pydoll/commands/bidi/emulation_commands.py
  • pydoll/commands/bidi/input_commands.py
  • pydoll/commands/bidi/network_commands.py
  • pydoll/commands/bidi/script_commands.py
  • pydoll/commands/bidi/session_commands.py
  • pydoll/commands/bidi/storage_commands.py
  • pydoll/commands/bidi/web_extension_commands.py
  • pydoll/commands/cdp/__init__.py
  • pydoll/commands/cdp/accessibility_commands.py
  • pydoll/commands/cdp/browser_commands.py
  • pydoll/commands/cdp/dom_commands.py
  • pydoll/commands/cdp/emulation_commands.py
  • pydoll/commands/cdp/fetch_commands.py
  • pydoll/commands/cdp/input_commands.py
  • pydoll/commands/cdp/network_commands.py
  • pydoll/commands/cdp/page_commands.py
  • pydoll/commands/cdp/runtime_commands.py
  • pydoll/commands/cdp/storage_commands.py
  • pydoll/commands/cdp/target_commands.py
  • pydoll/connection/base_connection_handler.py
  • pydoll/connection/bidi_connection_handler.py
  • pydoll/connection/connection_handler.py
  • pydoll/connection/managers/commands_manager.py
  • pydoll/connection/managers/event_trackers.py
  • pydoll/connection/managers/events_manager.py
  • pydoll/elements/bidi/__init__.py
  • pydoll/elements/bidi/web_element.py
  • pydoll/elements/cdp/__init__.py
  • pydoll/elements/cdp/shadow_root.py
  • pydoll/elements/cdp/web_element.py
  • pydoll/elements/mixins/bidi_find_elements_mixin.py
  • pydoll/elements/mixins/cdp_find_elements_mixin.py
  • pydoll/elements/mixins/find_elements_mixin.py
  • pydoll/elements/protocols.py
  • pydoll/exceptions.py
  • pydoll/extractor/__init__.py
  • pydoll/extractor/engine.py
  • pydoll/extractor/exceptions.py
  • pydoll/extractor/llm.py
  • pydoll/extractor/providers/__init__.py
  • pydoll/extractor/providers/anthropic.py
  • pydoll/extractor/providers/openai.py
  • pydoll/interactions/iframe.py
  • pydoll/interactions/keyboard.py
  • pydoll/interactions/mouse.py
  • pydoll/interactions/scroll.py
  • pydoll/protocol/bidi/__init__.py
  • pydoll/protocol/bidi/base.py
  • pydoll/protocol/bidi/browser/__init__.py
  • pydoll/protocol/bidi/browser/methods.py
  • pydoll/protocol/bidi/browser/types.py
  • pydoll/protocol/bidi/browsing_context/__init__.py
  • pydoll/protocol/bidi/browsing_context/events.py
  • pydoll/protocol/bidi/browsing_context/methods.py
  • pydoll/protocol/bidi/browsing_context/types.py
  • pydoll/protocol/bidi/emulation/__init__.py
  • pydoll/protocol/bidi/emulation/methods.py
  • pydoll/protocol/bidi/emulation/types.py
  • pydoll/protocol/bidi/input/__init__.py
  • pydoll/protocol/bidi/input/events.py
  • pydoll/protocol/bidi/input/methods.py
  • pydoll/protocol/bidi/input/types.py
  • pydoll/protocol/bidi/log/__init__.py
  • pydoll/protocol/bidi/log/events.py
  • pydoll/protocol/bidi/log/types.py
  • pydoll/protocol/bidi/network/__init__.py
  • pydoll/protocol/bidi/network/events.py
  • pydoll/protocol/bidi/network/methods.py
  • pydoll/protocol/bidi/network/types.py
  • pydoll/protocol/bidi/script/__init__.py
  • pydoll/protocol/bidi/script/events.py
  • pydoll/protocol/bidi/script/methods.py
  • pydoll/protocol/bidi/script/types.py
  • pydoll/protocol/bidi/session/__init__.py
  • pydoll/protocol/bidi/session/methods.py
  • pydoll/protocol/bidi/session/types.py
  • pydoll/protocol/bidi/storage/__init__.py
  • pydoll/protocol/bidi/storage/methods.py
  • pydoll/protocol/bidi/storage/types.py
  • pydoll/protocol/bidi/web_extension/__init__.py
  • pydoll/protocol/bidi/web_extension/methods.py
  • pydoll/protocol/bidi/web_extension/types.py
  • pydoll/protocol/cdp/__init__.py
  • pydoll/protocol/cdp/accessibility/__init__.py
  • pydoll/protocol/cdp/accessibility/events.py
  • pydoll/protocol/cdp/accessibility/methods.py
  • pydoll/protocol/cdp/accessibility/types.py
  • pydoll/protocol/cdp/base.py
  • pydoll/protocol/cdp/browser/__init__.py
  • pydoll/protocol/cdp/browser/events.py
  • pydoll/protocol/cdp/browser/methods.py
  • pydoll/protocol/cdp/browser/types.py
  • pydoll/protocol/cdp/debugger/types.py
  • pydoll/protocol/cdp/dom/__init__.py
  • pydoll/protocol/cdp/dom/events.py
  • pydoll/protocol/cdp/dom/methods.py
  • pydoll/protocol/cdp/dom/types.py
  • pydoll/protocol/cdp/emulation/__init__.py
  • pydoll/protocol/cdp/emulation/methods.py
  • pydoll/protocol/cdp/emulation/types.py
  • pydoll/protocol/cdp/fetch/__init__.py
  • pydoll/protocol/cdp/fetch/events.py
  • pydoll/protocol/cdp/fetch/methods.py
  • pydoll/protocol/cdp/fetch/types.py
  • pydoll/protocol/cdp/input/__init__.py
  • pydoll/protocol/cdp/input/events.py
  • pydoll/protocol/cdp/input/methods.py
  • pydoll/protocol/cdp/input/types.py
  • pydoll/protocol/cdp/io/types.py
  • pydoll/protocol/cdp/network/__init__.py
  • pydoll/protocol/cdp/network/events.py
  • pydoll/protocol/cdp/network/har_types.py
  • pydoll/protocol/cdp/network/methods.py
  • pydoll/protocol/cdp/network/types.py
  • pydoll/protocol/cdp/page/__init__.py
  • pydoll/protocol/cdp/page/events.py
  • pydoll/protocol/cdp/page/methods.py
  • pydoll/protocol/cdp/page/types.py
  • pydoll/protocol/cdp/runtime/__init__.py
  • pydoll/protocol/cdp/runtime/events.py
  • pydoll/protocol/cdp/runtime/methods.py
  • pydoll/protocol/cdp/runtime/types.py
  • pydoll/protocol/cdp/security/types.py
  • pydoll/protocol/cdp/storage/__init__.py
  • pydoll/protocol/cdp/storage/events.py
  • pydoll/protocol/cdp/storage/methods.py
  • pydoll/protocol/cdp/storage/types.py
  • pydoll/protocol/cdp/target/__init__.py
  • pydoll/protocol/cdp/target/events.py
  • pydoll/protocol/cdp/target/methods.py
  • pydoll/protocol/cdp/target/types.py
  • pydoll/protocol/events.py
  • pydoll/protocol/types.py
  • pydoll/utils/bundle.py
  • pydoll/utils/html_to_markdown.py
  • pydoll/utils/socks5_proxy_forwarder.py
  • pydoll/utils/user_agent_parser.py
  • tests/conftest.py
  • tests/test_browser/test_browser_base.py
  • tests/test_browser/test_browser_chrome.py
  • tests/test_browser/test_browser_edge.py
  • tests/test_browser/test_browser_options.py
  • tests/test_browser/test_browser_tab.py
  • tests/test_browser/test_har_recorder.py
  • tests/test_browser/test_requests_request.py
  • tests/test_browser/test_requests_response.py
  • tests/test_browser/test_tab_request_integration.py
  • tests/test_click_nested_integration.py
  • tests/test_commands/test_accessibility_commands.py
  • tests/test_commands/test_browser_commands.py
  • tests/test_commands/test_dom_commands.py
  • tests/test_commands/test_emulation_commands.py
  • tests/test_commands/test_fetch_commands.py
  • tests/test_commands/test_input_commands.py
  • tests/test_commands/test_network_commands.py
  • tests/test_commands/test_page_commands.py
  • tests/test_commands/test_runtime_commands.py
  • tests/test_commands/test_storage_commands.py
  • tests/test_commands/test_target_commands.py
  • tests/test_connection_handler.py
  • tests/test_core_integration.py
  • tests/test_events.py
  • tests/test_find_elements_mixin.py
  • tests/test_iframe_integration.py
  • tests/test_interactions/test_keyboard.py
  • tests/test_interactions/test_mouse.py
  • tests/test_interactions/test_scroll.py
  • tests/test_managers/test_browser_managers.py
  • tests/test_managers/test_connection_managers.py
  • tests/test_shadow_root.py
  • tests/test_shadow_root_integration.py
  • tests/test_web_element.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/firefox

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant