This commit is contained in:
Magnus Müller
2025-09-19 19:36:53 -07:00
parent 0aa3163693
commit 7e2d4de32c
8 changed files with 23 additions and 1 deletions
+3
View File
@@ -453,6 +453,7 @@ class BrowserSession(BaseModel):
BaseWatchdog.attach_handler_to_session(self, FileDownloadedEvent, self.on_FileDownloadedEvent)
BaseWatchdog.attach_handler_to_session(self, CloseTabEvent, self.on_CloseTabEvent)
@observe_debug(ignore_input=True, ignore_output=True, name='browser_session_start')
async def start(self) -> None:
"""Start the browser session."""
start_event = self.event_bus.dispatch(BrowserStartEvent())
@@ -499,6 +500,7 @@ class BrowserSession(BaseModel):
# Create fresh event bus
self.event_bus = EventBus()
@observe_debug(ignore_input=True, ignore_output=True, name='browser_start_event_handler')
async def on_BrowserStartEvent(self, event: BrowserStartEvent) -> dict[str, str]:
"""Handle browser start request.
@@ -2380,6 +2382,7 @@ class BrowserSession(BaseModel):
return await self.get_or_create_cdp_session()
@observe_debug(ignore_input=True, ignore_output=True, name='take_screenshot')
async def take_screenshot(
self,
path: str | None = None,
@@ -21,6 +21,7 @@ from browser_use.browser.events import (
from browser_use.browser.views import BrowserError, URLNotAllowedError
from browser_use.browser.watchdog_base import BaseWatchdog
from browser_use.dom.service import EnhancedDOMTreeNode
from browser_use.observability import observe_debug
# Import EnhancedDOMTreeNode and rebuild event models that have forward references to it
# This must be done after all imports are complete
@@ -35,6 +36,7 @@ UploadFileEvent.model_rebuild()
class DefaultActionWatchdog(BaseWatchdog):
"""Handles default browser actions like click, type, and scroll using CDP."""
@observe_debug(ignore_input=True, ignore_output=True, name='click_element_event')
async def on_ClickElementEvent(self, event: ClickElementEvent) -> dict | None:
"""Handle click request with CDP."""
try:
@@ -1516,6 +1518,7 @@ class DefaultActionWatchdog(BaseWatchdog):
except Exception as e:
raise
@observe_debug(ignore_input=True, ignore_output=True, name='wait_event_handler')
async def on_WaitEvent(self, event: WaitEvent) -> None:
"""Handle wait request."""
try:
@@ -85,6 +85,7 @@ class DOMWatchdog(BaseWatchdog):
return json.dumps([]) # Return empty JSON array on error
@observe_debug(ignore_input=True, ignore_output=True, name='browser_state_request_event')
async def on_BrowserStateRequestEvent(self, event: BrowserStateRequestEvent) -> 'BrowserStateSummary':
"""Handle browser state request by coordinating DOM building and screenshot capture.
@@ -18,6 +18,7 @@ from browser_use.browser.events import (
BrowserStopEvent,
)
from browser_use.browser.watchdog_base import BaseWatchdog
from browser_use.observability import observe_debug
if TYPE_CHECKING:
pass
@@ -42,6 +43,7 @@ class LocalBrowserWatchdog(BaseWatchdog):
_temp_dirs_to_cleanup: list[Path] = PrivateAttr(default_factory=list)
_original_user_data_dir: str | None = PrivateAttr(default=None)
@observe_debug(ignore_input=True, ignore_output=True, name='browser_launch_event')
async def on_BrowserLaunchEvent(self, event: BrowserLaunchEvent) -> BrowserLaunchResult:
"""Launch a local browser process."""
@@ -85,6 +87,7 @@ class LocalBrowserWatchdog(BaseWatchdog):
# Dispatch BrowserKillEvent without awaiting so it gets processed after all BrowserStopEvent handlers
self.event_bus.dispatch(BrowserKillEvent())
@observe_debug(ignore_input=True, ignore_output=True, name='launch_browser_process')
async def _launch_browser(self, max_retries: int = 3) -> tuple[psutil.Process, str]:
"""Launch browser process and return (process, cdp_url).
@@ -8,6 +8,7 @@ from cdp_use.cdp.page import CaptureScreenshotParameters
from browser_use.browser.events import ScreenshotEvent
from browser_use.browser.views import BrowserError
from browser_use.browser.watchdog_base import BaseWatchdog
from browser_use.observability import observe_debug
if TYPE_CHECKING:
pass
@@ -22,6 +23,7 @@ class ScreenshotWatchdog(BaseWatchdog):
# Events this watchdog emits
EMITS: ClassVar[list[type[BaseEvent[Any]]]] = []
@observe_debug(ignore_input=True, ignore_output=True, name='screenshot_event_handler')
async def on_ScreenshotEvent(self, event: ScreenshotEvent) -> str:
"""Handle screenshot request using CDP.
+3
View File
@@ -23,6 +23,7 @@ from browser_use.dom.views import (
SerializedDOMState,
TargetAllTrees,
)
from browser_use.observability import observe_debug
if TYPE_CHECKING:
from browser_use.browser.session import BrowserSession
@@ -446,6 +447,7 @@ class DomService:
cdp_timing=cdp_timing,
)
@observe_debug(ignore_input=True, ignore_output=True, name='get_dom_tree')
async def get_dom_tree(
self,
target_id: TargetID,
@@ -711,6 +713,7 @@ class DomService:
return enhanced_dom_tree_node
@observe_debug(ignore_input=True, ignore_output=True, name='get_serialized_dom_tree')
async def get_serialized_dom_tree(
self, previous_cached_state: SerializedDOMState | None = None
) -> tuple[SerializedDOMState, EnhancedDOMTreeNode, dict[str, float]]:
+4 -1
View File
@@ -75,7 +75,7 @@ class ChatGoogle(BaseChatModel):
temperature: float | None = 0.2
top_p: float | None = None
seed: int | None = None
thinking_budget: int | None = 0
thinking_budget: int | None = None
max_output_tokens: int | None = 4096
config: types.GenerateContentConfigDict | None = None
include_system_in_user: bool = False
@@ -198,6 +198,9 @@ class ChatGoogle(BaseChatModel):
if self.seed is not None:
config['seed'] = self.seed
if self.thinking_budget is None and 'gemini-2.5' in self.model:
self.thinking_budget = -1
if self.thinking_budget is not None:
thinking_config_dict: types.ThinkingConfigDict = {'thinking_budget': self.thinking_budget}
config['thinking_config'] = thinking_config_dict
+4
View File
@@ -7,6 +7,8 @@ from pathlib import Path
import anyio
from browser_use.observability import observe_debug
class ScreenshotService:
"""Simple screenshot storage service that saves screenshots to disk"""
@@ -19,6 +21,7 @@ class ScreenshotService:
self.screenshots_dir = self.agent_directory / 'screenshots'
self.screenshots_dir.mkdir(parents=True, exist_ok=True)
@observe_debug(ignore_input=True, ignore_output=True, name='store_screenshot')
async def store_screenshot(self, screenshot_b64: str, step_number: int) -> str:
"""Store screenshot to disk and return the full path as string"""
screenshot_filename = f'step_{step_number}.png'
@@ -32,6 +35,7 @@ class ScreenshotService:
return str(screenshot_path)
@observe_debug(ignore_input=True, ignore_output=True, name='get_screenshot_from_disk')
async def get_screenshot(self, screenshot_path: str) -> str | None:
"""Load screenshot from disk path and return as base64"""
if not screenshot_path: