Skip to content

Commit 014a6b8

Browse files
sundargthbSundar Raghavan
andauthored
feat(browser): Add viewport configuration support to BrowserClient (#112)
Add viewport optional parameter to the BrowserClient.start() method to properly configure browser viewport dimensions through the underlying StartBrowserSession API. Co-authored-by: Sundar Raghavan <[email protected]>
1 parent ee35ade commit 014a6b8

File tree

3 files changed

+74
-19
lines changed

3 files changed

+74
-19
lines changed

src/bedrock_agentcore/tools/browser_client.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def start(
9999
identifier: Optional[str] = DEFAULT_IDENTIFIER,
100100
name: Optional[str] = None,
101101
session_timeout_seconds: Optional[int] = DEFAULT_SESSION_TIMEOUT,
102+
viewport: Optional[Dict[str, int]] = None,
102103
) -> str:
103104
"""Start a browser sandbox session.
104105
@@ -111,19 +112,31 @@ def start(
111112
will be generated using a UUID.
112113
session_timeout_seconds (Optional[int]): The timeout for the session in seconds.
113114
Defaults to DEFAULT_TIMEOUT.
114-
description (Optional[str]): A description for this session.
115-
Defaults to an empty string.
115+
viewport (Optional[Dict[str, int]]): The viewport dimensions for the browser.
116+
Should be a dict with 'width' and 'height' keys (e.g., {'width': 1920, 'height': 1080}).
117+
If not provided, the service default viewport will be used.
116118
117119
Returns:
118120
str: The session ID of the newly created session.
121+
122+
Example:
123+
>>> client = BrowserClient('us-west-2')
124+
>>> session_id = client.start(viewport={'width': 1920, 'height': 1080})
119125
"""
120126
self.logger.info("Starting browser session...")
121127

122-
response = self.client.start_browser_session(
123-
browserIdentifier=identifier,
124-
name=name or f"browser-session-{uuid.uuid4().hex[:8]}",
125-
sessionTimeoutSeconds=session_timeout_seconds,
126-
)
128+
# Build the request parameters
129+
request_params = {
130+
"browserIdentifier": identifier,
131+
"name": name or f"browser-session-{uuid.uuid4().hex[:8]}",
132+
"sessionTimeoutSeconds": session_timeout_seconds,
133+
}
134+
135+
# Add viewport if provided
136+
if viewport is not None:
137+
request_params["viewPort"] = viewport
138+
139+
response = self.client.start_browser_session(**request_params)
127140

128141
self.identifier = response["browserIdentifier"]
129142
self.session_id = response["sessionId"]
@@ -306,26 +319,18 @@ def _update_browser_stream(self, identifier: str, session_id: str, stream_status
306319

307320

308321
@contextmanager
309-
def browser_session(region: str) -> Generator[BrowserClient, None, None]:
322+
def browser_session(region: str, viewport: Optional[Dict[str, int]] = None) -> Generator[BrowserClient, None, None]:
310323
"""Context manager for creating and managing a browser sandbox session.
311324
312-
This context manager handles creating a client, starting a session, and
313-
ensuring the session is properly cleaned up when the context exits.
314-
315325
Args:
316326
region (str): The AWS region to use for the Browser service.
327+
viewport (Optional[Dict[str, int]]): The viewport dimensions for the browser.
317328
318329
Yields:
319330
BrowserClient: An initialized and started browser client.
320-
321-
Example:
322-
>>> with browser_session('us-west-2') as client:
323-
... browser = client.get_browser_obj()
324-
... page = browser.new_page()
325-
... page.goto('https://example.com')
326331
"""
327332
client = BrowserClient(region)
328-
client.start()
333+
client.start(viewport=viewport)
329334

330335
try:
331336
yield client

tests/bedrock_agentcore/tools/test_browser_client.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,12 @@ def test_start_with_defaults(self, mock_uuid4, mock_boto3):
7171
assert client.session_id == "session-123"
7272

7373
@patch("bedrock_agentcore.tools.browser_client.boto3")
74-
def test_start_with_custom_params(self, mock_boto3):
74+
@patch("bedrock_agentcore.tools.browser_client.uuid.uuid4")
75+
def test_start_with_custom_params(self, mock_uuid4, mock_boto3):
7576
# Arrange
7677
mock_client = MagicMock()
7778
mock_boto3.client.return_value = mock_client
79+
mock_uuid4.return_value.hex = "12345678abcdef"
7880

7981
client = BrowserClient("us-west-2")
8082
mock_response = {"browserIdentifier": "custom.browser", "sessionId": "custom-session-123"}
@@ -361,3 +363,46 @@ def test_release_control(self, mock_boto3):
361363
sessionId="test-session-id",
362364
streamUpdate={"automationStreamUpdate": {"streamStatus": "ENABLED"}},
363365
)
366+
367+
@patch("bedrock_agentcore.tools.browser_client.boto3")
368+
@patch("bedrock_agentcore.tools.browser_client.uuid.uuid4")
369+
def test_start_with_viewport(self, mock_uuid4, mock_boto3):
370+
# Arrange
371+
mock_client = MagicMock()
372+
mock_boto3.client.return_value = mock_client
373+
mock_uuid4.return_value.hex = "12345678abcdef"
374+
375+
client = BrowserClient("us-west-2")
376+
mock_response = {"browserIdentifier": "aws.browser.v1", "sessionId": "session-123"}
377+
mock_client.start_browser_session.return_value = mock_response
378+
viewport = {"width": 1920, "height": 1080}
379+
380+
# Act
381+
session_id = client.start(viewport=viewport)
382+
383+
# Assert
384+
mock_client.start_browser_session.assert_called_once_with(
385+
browserIdentifier="aws.browser.v1",
386+
name="browser-session-12345678",
387+
sessionTimeoutSeconds=3600,
388+
viewPort=viewport,
389+
)
390+
assert session_id == "session-123"
391+
assert client.identifier == "aws.browser.v1"
392+
assert client.session_id == "session-123"
393+
394+
@patch("bedrock_agentcore.tools.browser_client.BrowserClient")
395+
def test_browser_session_context_manager_with_viewport(self, mock_client_class):
396+
# Arrange
397+
mock_client = MagicMock()
398+
mock_client_class.return_value = mock_client
399+
viewport = {"width": 1280, "height": 720}
400+
401+
# Act
402+
with browser_session("us-west-2", viewport=viewport):
403+
pass
404+
405+
# Assert
406+
mock_client_class.assert_called_once_with("us-west-2")
407+
mock_client.start.assert_called_once_with(viewport=viewport)
408+
mock_client.stop.assert_called_once()

tests_integ/tools/test_browser.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@
1010

1111
client.take_control()
1212
client.release_control()
13+
14+
with browser_session("us-west-2", viewport={"width": 1280, "height": 720}) as client:
15+
assert client.session_id is not None
16+
url, headers = client.generate_ws_headers()
17+
assert url.startswith("wss")

0 commit comments

Comments
 (0)