-
Notifications
You must be signed in to change notification settings - Fork 7.8k
local-remote-split-type-fix-auto-enter #2636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…to new-extraction-layer-magnus
…detection/download. mostly coded by claude-opus-4.1
…rowser-use into local-remote-split
…Introduced methods for cleaning HTML, validating content relevance, and intelligently truncating long content. Enhanced markdown conversion and improved error handling for content extraction failures.
…TML to markdown conversion using markdownify, improved error handling, and streamlined memory management for extracted content. Removed obsolete methods related to HTML cleaning and content validation.
🚨 Bugbot Trial ExpiredYour Bugbot trial has expired. Please purchase a license in the Cursor dashboard to continue using Bugbot. |
assert len(browser_session.tabs) == initial_tabs_count + 1 | ||
|
||
# Verify focus switched to the new tab | ||
assert 'example.com' in current_url |
Check failure
Code scanning / CodeQL
Incomplete URL substring sanitization High test
example.com
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 16 hours ago
To fix the problem, we should parse the current_url
using Python's urllib.parse
module and check the hostname component directly, rather than using a substring check. Specifically, we should use urlparse(current_url).hostname
and verify that it matches example.com
or ends with .example.com
(if subdomains are allowed). In this test, since the navigation is to 'https://example.com'
, a strict equality check is appropriate.
Steps:
- Import
urlparse
fromurllib.parse
at the top of the file (if not already imported). - Replace the substring check (
'example.com' in current_url
) with a check on the parsed hostname:urlparse(current_url).hostname == 'example.com'
.
-
Copy modified line R5 -
Copy modified line R399
@@ -4,3 +4,3 @@ | ||
from pytest_httpserver import HTTPServer | ||
|
||
from urllib.parse import urlparse | ||
from browser_use.agent.views import ActionModel, ActionResult | ||
@@ -398,3 +398,3 @@ | ||
# Verify focus switched to the new tab | ||
assert 'example.com' in current_url | ||
assert urlparse(current_url).hostname == 'example.com' | ||
assert current_url != initial_url |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cubic analysis
27 issues found across 90 files • Review in cubic
React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai
to give feedback, ask questions, or re-run the review.
params={'expression': 'window.pageYOffset', 'returnByValue': True}, | ||
session_id=cdp_session.session_id, | ||
) | ||
main_y = main_scroll.get('result', {}).get('value', 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable main_y is assigned but never used, which will raise an unused-variable warning in most linters and can block CI. Replace it with _ or remove the assignment to indicate the value is intentionally ignored. (Based on your team's feedback about keeping the codebase free of linter warnings.)
Prompt for AI agents
Address the following comment on tests/ci/test_action_ScrollEvent.py at line 379:
<comment>The variable main_y is assigned but never used, which will raise an unused-variable warning in most linters and can block CI. Replace it with _ or remove the assignment to indicate the value is intentionally ignored. (Based on your team's feedback about keeping the codebase free of linter warnings.)</comment>
<file context>
@@ -0,0 +1,423 @@
+import asyncio
+
+import pytest
+from pytest_httpserver import HTTPServer
+
+from browser_use.agent.views import ActionModel, ActionResult
+from browser_use.browser import BrowserSession
+from browser_use.browser.profile import BrowserProfile
+from browser_use.controller.service import Controller
</file context>
main_y = main_scroll.get('result', {}).get('value', 0) | |
_ = main_scroll.get('result', {}).get('value', 0) |
session = BrowserSession(browser_profile=profile) | ||
|
||
# Track BrowserErrorEvents | ||
error_events = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test collects BrowserErrorEvent instances but never asserts that the list remains empty, so the test will pass even when unexpected errors occur.
Prompt for AI agents
Address the following comment on tests/ci/test_security_watchdog.py at line 80:
<comment>The test collects BrowserErrorEvent instances but never asserts that the list remains empty, so the test will pass even when unexpected errors occur.</comment>
<file context>
@@ -0,0 +1,155 @@
+"""Test navigation and security functionality."""
+
+from typing import cast
+
+import pytest
+
+from browser_use.browser.events import (
+ BrowserConnectedEvent,
+ BrowserErrorEvent,
</file context>
cdp_timing: dict[str, float] | ||
|
||
|
||
@dataclass(slots=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mutable dataclass defines a custom hash but is not frozen, so the hash can change after mutation, breaking dictionary/set invariants and leading to hard-to-trace bugs.
Prompt for AI agents
Address the following comment on browser_use/dom/views.py at line 52:
<comment>Mutable dataclass defines a custom __hash__ but is not frozen, so the hash can change after mutation, breaking dictionary/set invariants and leading to hard-to-trace bugs.</comment>
<file context>
@@ -70,220 +31,467 @@ def __json__(self) -> dict:
]
-@dataclass(frozen=False)
-class DOMElementNode(DOMBaseNode):
+@dataclass
+class CurrentPageTargets:
+ page_session: TargetInfo
+ iframe_sessions: list[TargetInfo]
</file context>
@dataclass(slots=True) | |
@dataclass(slots=True, frozen=True) |
async def test_no_leaked_asyncio_tasks(): | ||
"""Test that no asyncio tasks remain after agent shutdown.""" | ||
# Get initial tasks | ||
initial_tasks = asyncio.all_tasks(asyncio.get_event_loop()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling asyncio.get_event_loop() inside a running coroutine is deprecated; use asyncio.get_running_loop() or omit the argument to all_tasks() instead.
Prompt for AI agents
Address the following comment on tests/ci/test_agent_shutdown.py at line 43:
<comment>Calling asyncio.get_event_loop() inside a running coroutine is deprecated; use asyncio.get_running_loop() or omit the argument to all_tasks() instead.</comment>
<file context>
@@ -0,0 +1,163 @@
+"""Test agent shutdown and cleanup."""
+
+import asyncio
+import logging
+import threading
+import time
+
+from browser_use import Agent, BrowserProfile, BrowserSession
+from tests.ci.conftest import create_mock_llm
</file context>
|
||
await inject_highlighting_script(dom_service, serialized_dom_state.selector_map) | ||
|
||
input('Done. Press Enter to continue...') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling the synchronous built-in input() inside an async loop blocks the event loop, defeating concurrency and potentially freezing other coroutines.
Prompt for AI agents
Address the following comment on browser_use/dom/playground/tree.py at line 124:
<comment>Calling the synchronous built-in input() inside an async loop blocks the event loop, defeating concurrency and potentially freezing other coroutines.</comment>
<file context>
@@ -0,0 +1,128 @@
+import asyncio
+import json
+import time
+
+import aiofiles
+
+from browser_use.browser import BrowserProfile, BrowserSession
+from browser_use.browser.types import ViewportSize
+from browser_use.dom.debug.highlights import inject_highlighting_script, remove_highlighting_script
</file context>
input('Done. Press Enter to continue...') | |
await asyncio.to_thread(input, 'Done. Press Enter to continue...') |
page = await browser_session.get_current_page() | ||
page_info = browser_session.browser_state_summary.page_info | ||
# Get browser state summary | ||
state = await browser_session.get_browser_state_summary() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
page
is now undefined due to removal of its assignment, causing a runtime NameError when handle_model_action(page, action)
is called. (Based on your team's feedback about prioritizing critical runtime issues)
Prompt for AI agents
Address the following comment on examples/custom-functions/cua.py at line 134:
<comment>`page` is now undefined due to removal of its assignment, causing a runtime NameError when `handle_model_action(page, action)` is called. (Based on your team's feedback about prioritizing critical runtime issues)</comment>
<file context>
@@ -130,14 +130,15 @@ async def openai_cua_fallback(params: OpenAICUAAction, browser_session: BrowserS
print(f'🎯 CUA Action Starting - Goal: {params.description}')
try:
- page = await browser_session.get_current_page()
- page_info = browser_session.browser_state_summary.page_info
+ # Get browser state summary
+ state = await browser_session.get_browser_state_summary()
+ page_info = state.page_info
if not page_info:
</file context>
|
||
|
||
@pytest.mark.asyncio | ||
async def test_watchdog_integration_with_session_lifecycle(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first test is missing a try/finally tear-down; if an earlier assertion fails the browser session is left alive, leaking resources and jeopardising later tests.
Prompt for AI agents
Address the following comment on tests/ci/test_watchdog.py at line 21:
<comment>The first test is missing a try/finally tear-down; if an earlier assertion fails the browser session is left alive, leaking resources and jeopardising later tests.</comment>
<file context>
@@ -0,0 +1,107 @@
+"""Test browser watchdog integration and lifecycle."""
+
+from typing import cast
+
+import pytest
+
+from browser_use.browser.events import (
+ BrowserConnectedEvent,
+ BrowserStartEvent,
</file context>
) | ||
url = result.get('result', {}).get('value', '') | ||
return 'login' in url.lower() or 'signin' in url.lower() | ||
except: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bare except clause suppresses all exceptions and obscures underlying errors; catch a specific exception class instead or use "except Exception" with logging. (Based on your team's feedback about improving error handling and avoiding overly broad exception catching.)
Prompt for AI agents
Address the following comment on examples/custom-functions/action_filters.py at line 71:
<comment>Bare except clause suppresses all exceptions and obscures underlying errors; catch a specific exception class instead or use "except Exception" with logging. (Based on your team's feedback about improving error handling and avoiding overly broad exception catching.)</comment>
<file context>
@@ -39,29 +38,58 @@ async def some_action(browser_session: BrowserSession):
# Action will only be available to Agent on Google domains because of the domain filter
@registry.action(description='Trigger disco mode', domains=['google.com', '*.google.com'])
-async def disco_mode(page: Page):
- await page.evaluate("""() => {
- // define the wiggle animation
- document.styleSheets[0].insertRule('@keyframes wiggle { 0% { transform: rotate(0deg); } 50% { transform: rotate(10deg); } 100% { transform: rotate(0deg); } }');
-
- document.querySelectorAll("*").forEach(element => {
</file context>
except: | |
except Exception: |
event_names = { | ||
name.split('[')[0] | ||
for name in globals().keys() | ||
if not name.startswith('_') and issubclass(globals()[name], BaseEvent) and name != 'BaseEvent' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling issubclass() on non-class globals will raise TypeError and crash the module import; ensure the object is a type before invoking issubclass() (Based on your team's feedback about catching runtime errors early).
Prompt for AI agents
Address the following comment on browser_use/browser/events.py at line 372:
<comment>Calling issubclass() on non-class globals will raise TypeError and crash the module import; ensure the object is a type before invoking issubclass() (Based on your team's feedback about catching runtime errors early).</comment>
<file context>
@@ -0,0 +1,380 @@
+"""Event definitions for browser communication."""
+
+from typing import Any, Literal
+
+from bubus import BaseEvent
+from bubus.models import T_EventResultType
+from pydantic import Field, field_validator
+
+from browser_use.browser.views import BrowserStateSummary
</file context>
# Navigate to a test page | ||
await page.goto('https://example.com', wait_until='load') | ||
# Navigate to a test page using events | ||
nav_event = browser_session.event_bus.dispatch(NavigateToUrlEvent(url='https://example.com')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awaiting the dispatched NavigateToUrlEvent only waits for handlers to finish, but BrowserSession.on_NavigateToUrlEvent does not block until the requested page is fully loaded (it only sleeps 0.5 s). Subsequent size checks may run before navigation completes, leading to flaky example behaviour.
Prompt for AI agents
Address the following comment on examples/browser/window_sizing.py at line 65:
<comment>Awaiting the dispatched NavigateToUrlEvent only waits for handlers to finish, but BrowserSession.on_NavigateToUrlEvent does not block until the requested page is fully loaded (it only sleeps 0.5 s). Subsequent size checks may run before navigation completes, leading to flaky example behaviour.</comment>
<file context>
@@ -40,17 +61,15 @@ async def example_custom_window_size():
)
await browser_session.start()
- # Get the current page
- page = await browser_session.get_current_page()
-
- # Navigate to a test page
- await page.goto('https://example.com', wait_until='load')
+ # Navigate to a test page using events
</file context>
…mote-split-type-fix-auto-enter
Auto-generated PR for branch: local-remote-split-type-fix-auto-enter
Summary by cubic
Migrated browser automation from Playwright to a pure Chrome DevTools Protocol (CDP) event-driven architecture, refactoring BrowserSession and related modules for improved reliability, extensibility, and testability.