Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/bedrock_agentcore/tools/browser_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ def browser_session(
region: str,
viewport: Optional[Union[ViewportConfiguration, Dict[str, int]]] = None,
identifier: Optional[str] = None,
name: Optional[str] = None,
proxy_configuration: Optional[Union[ProxyConfiguration, Dict[str, Any]]] = None,
extensions: Optional[List[Union[BrowserExtension, Dict[str, Any]]]] = None,
profile_configuration: Optional[Union[ProfileConfiguration, Dict[str, Any]]] = None,
Expand All @@ -640,6 +641,7 @@ def browser_session(
viewport (Optional[Union[ViewportConfiguration, Dict[str, int]]]): Viewport dimensions.
Can be a ViewportConfiguration dataclass or a plain dict.
identifier (Optional[str]): Browser identifier (system or custom).
name (Optional[str]): A name for this session.
proxy_configuration (Optional[Union[ProxyConfiguration, Dict[str, Any]]]): Proxy
configuration. Can be a ProxyConfiguration dataclass or a plain dict.
extensions (Optional[List[Union[BrowserExtension, Dict[str, Any]]]]): Browser
Expand All @@ -660,6 +662,10 @@ def browser_session(
... # Automation with reduced CAPTCHA friction
... pass
...
>>> # Use named session
>>> with browser_session('us-west-2', name='my-research-session') as client:
... ws_url, headers = client.generate_ws_headers()
...
>>> # Use proxy configuration
>>> with browser_session('us-west-2', proxy_configuration={
... "proxies": [{"externalProxy": {"server": "proxy.corp.com", "port": 8080}}],
Expand All @@ -673,6 +679,8 @@ def browser_session(
start_kwargs["viewport"] = viewport
if identifier is not None:
start_kwargs["identifier"] = identifier
if name is not None:
start_kwargs["name"] = name
if proxy_configuration is not None:
start_kwargs["proxy_configuration"] = proxy_configuration
if extensions is not None:
Expand Down
4 changes: 4 additions & 0 deletions src/bedrock_agentcore/tools/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,12 +341,14 @@ class SessionConfiguration:
Usage: client.start(**session_config.to_dict())

Attributes:
name: Optional name for the session
viewport: Viewport dimensions for the browser session
proxy: Proxy configuration for routing browser traffic
extensions: Browser extensions to load into the session
profile: Profile configuration for persisting browser state
"""

name: Optional[str] = None
viewport: Optional[ViewportConfiguration] = None
proxy: Optional[ProxyConfiguration] = None
extensions: Optional[List[BrowserExtension]] = None
Expand All @@ -355,6 +357,8 @@ class SessionConfiguration:
def to_dict(self) -> Dict:
"""Convert to API-compatible dictionary."""
config = {}
if self.name is not None:
config["name"] = self.name
if self.viewport:
config["viewport"] = self.viewport.to_dict()
if self.proxy:
Expand Down
85 changes: 85 additions & 0 deletions tests/bedrock_agentcore/tools/test_browser_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
ProfileConfiguration,
ProxyConfiguration,
ProxyCredentials,
SessionConfiguration,
ViewportConfiguration,
)

Expand Down Expand Up @@ -1359,3 +1360,87 @@ def test_browser_session_accepts_dataclass_params(self, mock_client_class):
profile_configuration=profile,
)
mock_client.stop.assert_called_once()

@patch("bedrock_agentcore.tools.browser_client.BrowserClient")
def test_browser_session_context_manager_with_name(self, mock_client_class):
# Arrange
mock_client = MagicMock()
mock_client_class.return_value = mock_client

# Act
with browser_session("us-west-2", name="my-session"):
pass

# Assert
mock_client_class.assert_called_once_with("us-west-2")
mock_client.start.assert_called_once_with(name="my-session")
mock_client.stop.assert_called_once()

@patch("bedrock_agentcore.tools.browser_client.BrowserClient")
def test_browser_session_context_manager_with_name_and_all_params(self, mock_client_class):
# Arrange
mock_client = MagicMock()
mock_client_class.return_value = mock_client
viewport = {"width": 1280, "height": 720}
proxy_config = {
"proxies": [
{
"externalProxy": {
"server": "proxy.example.com",
"port": 8080,
}
}
],
}
extensions = [{"location": {"s3": {"bucket": "my-bucket", "prefix": "extensions/my-ext"}}}]
profile_config = {"profileIdentifier": "my-profile-id"}

# Act
with browser_session(
"us-west-2",
viewport=viewport,
identifier="custom-browser",
name="my-named-session",
proxy_configuration=proxy_config,
extensions=extensions,
profile_configuration=profile_config,
):
pass

# Assert
mock_client_class.assert_called_once_with("us-west-2")
mock_client.start.assert_called_once_with(
viewport=viewport,
identifier="custom-browser",
name="my-named-session",
proxy_configuration=proxy_config,
extensions=extensions,
profile_configuration=profile_config,
)
mock_client.stop.assert_called_once()

def test_session_configuration_with_name(self):
# Arrange
config = SessionConfiguration(name="test")

# Act
result = config.to_dict()

# Assert
assert result == {"name": "test"}

def test_session_configuration_with_name_and_viewport(self):
# Arrange
config = SessionConfiguration(
name="test-session",
viewport=ViewportConfiguration(width=1920, height=1080),
)

# Act
result = config.to_dict()

# Assert
assert result == {
"name": "test-session",
"viewport": {"width": 1920, "height": 1080},
}
8 changes: 8 additions & 0 deletions tests_integ/tools/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,11 @@
url, headers = client.generate_ws_headers()
assert url.startswith("wss")
print("✅ Test 2 passed")

# Test 3: Browser session with custom name
print("\nTest 3: Browser session with custom name")
with browser_session("us-west-2", name="sdk-integ-test-session") as client:
assert client.session_id is not None
session_info = client.get_session()
assert session_info.get("name") == "sdk-integ-test-session"
print("✅ Test 3 passed")
Loading