Skip to content

Commit 41bdcba

Browse files
add nottebrowser skeleton
1 parent eb2d58b commit 41bdcba

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

computers/nottebrowser.py

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import os
2+
from typing import Tuple, Dict, List, Union, Optional
3+
from playwright.sync_api import Browser, Page, BrowserContext, Error as PlaywrightError
4+
from .base_playwright import BasePlaywrightComputer
5+
from notte.sdk.client import NotteClient
6+
from dotenv import load_dotenv
7+
import base64
8+
9+
_ = load_dotenv()
10+
11+
12+
class NotteBrowser(BasePlaywrightComputer):
13+
"""
14+
Browserbase is a headless browser platform that offers a remote browser API. You can use it to control thousands of browsers from anywhere.
15+
You can find more information about Browserbase at https://www.browserbase.com/computer-use or view our OpenAI CUA Quickstart at https://docs.browserbase.com/integrations/openai-cua/introduction.
16+
17+
IMPORTANT: This Browserbase computer requires the use of the `goto` tool defined in playwright_with_custom_functions.py.
18+
Make sure to include this tool in your configuration when using the Browserbase computer.
19+
"""
20+
21+
def __init__(
22+
self,
23+
width: int = 1024,
24+
height: int = 768,
25+
proxy: bool = False,
26+
):
27+
"""
28+
Initialize the Browserbase instance. Additional configuration options for features such as persistent cookies, ad blockers, file downloads and more can be found in the Browserbase API documentation: https://docs.browserbase.com/reference/api/create-a-session
29+
30+
Args:
31+
width (int): The width of the browser viewport. Default is 1024.
32+
height (int): The height of the browser viewport. Default is 768.
33+
region (str): The region for the Browserbase session. Default is "us-west-2". Pick a region close to you for better performance. https://docs.browserbase.com/guides/multi-region
34+
proxy (bool): Whether to use a proxy for the session. Default is False. Turn on proxies if you're browsing is frequently interrupted. https://docs.browserbase.com/features/proxies
35+
virtual_mouse (bool): Whether to enable the virtual mouse cursor. Default is True.
36+
ad_blocker (bool): Whether to enable the built-in ad blocker. Default is False.
37+
"""
38+
super().__init__()
39+
self.notte = NotteClient(api_key=os.getenv("NOTTE_API_KEY"))
40+
self.session = None
41+
self.dimensions = (width, height)
42+
self.proxy = proxy
43+
44+
def _get_browser_and_page(self) -> Tuple[Browser, Page]:
45+
"""
46+
Create a Browserbase session and connect to it.
47+
48+
Returns:
49+
Tuple[Browser, Page]: A tuple containing the connected browser and page objects.
50+
"""
51+
# Create a session on Browserbase with specified parameters
52+
width, height = self.dimensions
53+
self.session = self.notte.sessions.start()#proxies=self.proxy)
54+
info =self.notte.sessions.debug_info(self.session.session_id)
55+
56+
# Print the live session URL
57+
print(
58+
f"Watch and control this browser live at https://www.browserbase.com/sessions/{self.session.id}"
59+
)
60+
61+
# Connect to the remote session
62+
browser = self._playwright.chromium.connect_over_cdp(
63+
info.debug_url,
64+
timeout=60000
65+
)
66+
context = browser.contexts[0]
67+
68+
# Add event listeners for page creation and closure
69+
context.on("page", self._handle_new_page)
70+
71+
72+
page = context.pages[0]
73+
page.on("close", self._handle_page_close)
74+
75+
page.goto("https://bing.com")
76+
77+
return browser, page
78+
79+
def _handle_new_page(self, page: Page):
80+
"""Handle the creation of a new page."""
81+
print("New page created")
82+
self._page = page
83+
page.on("close", self._handle_page_close)
84+
85+
def _handle_page_close(self, page: Page):
86+
"""Handle the closure of a page."""
87+
print("Page closed")
88+
if self._page == page:
89+
if self._browser.contexts[0].pages:
90+
self._page = self._browser.contexts[0].pages[-1]
91+
else:
92+
print("Warning: All pages have been closed.")
93+
self._page = None
94+
95+
def __exit__(self, exc_type, exc_val, exc_tb):
96+
"""
97+
Clean up resources when exiting the context manager.
98+
99+
Args:
100+
exc_type: The type of the exception that caused the context to be exited.
101+
exc_val: The exception instance that caused the context to be exited.
102+
exc_tb: A traceback object encapsulating the call stack at the point where the exception occurred.
103+
"""
104+
if self._page:
105+
self._page.close()
106+
if self._browser:
107+
self._browser.close()
108+
if self._playwright:
109+
self._playwright.stop()
110+
111+
if self.session:
112+
print(
113+
f"Session completed. View replay at https://browserbase.com/sessions/{self.session.id}"
114+
)
115+
116+
def screenshot(self) -> str:
117+
"""
118+
Capture a screenshot of the current viewport using CDP.
119+
120+
Returns:
121+
str: A base64 encoded string of the screenshot.
122+
"""
123+
try:
124+
# Get CDP session from the page
125+
cdp_session = self._page.context.new_cdp_session(self._page)
126+
127+
# Capture screenshot using CDP
128+
result = notte..send("Page.captureScreenshot", {
129+
"format": "png",
130+
"fromSurface": True
131+
})
132+
133+
return result['data']
134+
except PlaywrightError as error:
135+
print(f"CDP screenshot failed, falling back to standard screenshot: {error}")
136+
return super().screenshot()

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ scrapybara>=2.3.6
2121
sniffio==1.3.1
2222
typing_extensions==4.12.2
2323
urllib3==2.3.0
24+
notte==1.3.3

0 commit comments

Comments
 (0)