diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 544a78b3..9a723e88 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.22.0" + ".": "3.23.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index d8a50f3d..ffba0d92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 3.23.0 (2026-08-19) + +Full Changelog: [v3.22.0...v3.23.0](https://github.com/browserbase/stagehand-python/compare/v3.22.0...v3.23.0) + +### Features + +* expose `use_touch` for session start ([#364](https://github.com/browserbase/stagehand-python/pull/364)) + ## 3.22.0 (2026-07-21) Full Changelog: [v3.21.0...v3.22.0](https://github.com/browserbase/stagehand-python/compare/v3.21.0...v3.22.0) diff --git a/pyproject.toml b/pyproject.toml index a824d4a0..24d2b8f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "stagehand" -version = "3.22.0" +version = "3.23.0" description = "The official Python library for the stagehand API" dynamic = ["readme"] license = "MIT" diff --git a/src/stagehand/_custom/session.py b/src/stagehand/_custom/session.py index 4ca99711..bf5c1946 100644 --- a/src/stagehand/_custom/session.py +++ b/src/stagehand/_custom/session.py @@ -725,6 +725,7 @@ def _sync_start( *, model_name: str, act_timeout_ms: float | Omit = omit, + use_touch: bool | Omit = omit, browser: session_start_params.Browser | Omit = omit, browserbase_session_create_params: session_start_params.BrowserbaseSessionCreateParams | Omit = omit, browserbase_session_id: str | Omit = omit, @@ -744,6 +745,7 @@ def _sync_start( self, model_name=model_name, act_timeout_ms=act_timeout_ms, + use_touch=use_touch, browser=_resolve_start_browser(self._client, browser), browserbase_session_create_params=browserbase_session_create_params, browserbase_session_id=browserbase_session_id, @@ -769,6 +771,7 @@ async def _async_start( *, model_name: str, act_timeout_ms: float | Omit = omit, + use_touch: bool | Omit = omit, browser: session_start_params.Browser | Omit = omit, browserbase_session_create_params: session_start_params.BrowserbaseSessionCreateParams | Omit = omit, browserbase_session_id: str | Omit = omit, @@ -788,6 +791,7 @@ async def _async_start( self, model_name=model_name, act_timeout_ms=act_timeout_ms, + use_touch=use_touch, browser=_resolve_start_browser(self._client, browser), browserbase_session_create_params=browserbase_session_create_params, browserbase_session_id=browserbase_session_id, diff --git a/src/stagehand/_version.py b/src/stagehand/_version.py index ee7fca47..aeeeb9a3 100644 --- a/src/stagehand/_version.py +++ b/src/stagehand/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "stagehand" -__version__ = "3.22.0" # x-release-please-version +__version__ = "3.23.0" # x-release-please-version diff --git a/src/stagehand/resources/sessions.py b/src/stagehand/resources/sessions.py index a3c3c4bd..8c46e49b 100644 --- a/src/stagehand/resources/sessions.py +++ b/src/stagehand/resources/sessions.py @@ -922,6 +922,7 @@ def start( *, model_name: str, act_timeout_ms: float | Omit = omit, + use_touch: bool | Omit = omit, browser: session_start_params.Browser | Omit = omit, browserbase_session_create_params: session_start_params.BrowserbaseSessionCreateParams | Omit = omit, browserbase_session_id: str | Omit = omit, @@ -953,6 +954,8 @@ def start( act_timeout_ms: Timeout in ms for act operations (deprecated, v2 only) + use_touch: Actuate coordinate pointer actions as trusted touch taps instead of mouse input for mobile layouts + browserbase_session_id: Existing Browserbase session ID to resume dom_settle_timeout_ms: Timeout in ms to wait for DOM to settle @@ -992,6 +995,7 @@ def start( { "model_name": model_name, "act_timeout_ms": act_timeout_ms, + "use_touch": use_touch, "browser": browser, "browserbase_session_create_params": browserbase_session_create_params, "browserbase_session_id": browserbase_session_id, @@ -1885,6 +1889,7 @@ async def start( *, model_name: str, act_timeout_ms: float | Omit = omit, + use_touch: bool | Omit = omit, browser: session_start_params.Browser | Omit = omit, browserbase_session_create_params: session_start_params.BrowserbaseSessionCreateParams | Omit = omit, browserbase_session_id: str | Omit = omit, @@ -1916,6 +1921,8 @@ async def start( act_timeout_ms: Timeout in ms for act operations (deprecated, v2 only) + use_touch: Actuate coordinate pointer actions as trusted touch taps instead of mouse input for mobile layouts + browserbase_session_id: Existing Browserbase session ID to resume dom_settle_timeout_ms: Timeout in ms to wait for DOM to settle @@ -1955,6 +1962,7 @@ async def start( { "model_name": model_name, "act_timeout_ms": act_timeout_ms, + "use_touch": use_touch, "browser": browser, "browserbase_session_create_params": browserbase_session_create_params, "browserbase_session_id": browserbase_session_id, diff --git a/src/stagehand/types/session_start_params.py b/src/stagehand/types/session_start_params.py index c13fd036..4dce7bec 100644 --- a/src/stagehand/types/session_start_params.py +++ b/src/stagehand/types/session_start_params.py @@ -34,6 +34,9 @@ class SessionStartParams(TypedDict, total=False): act_timeout_ms: Annotated[float, PropertyInfo(alias="actTimeoutMs")] """Timeout in ms for act operations (deprecated, v2 only)""" + use_touch: Annotated[bool, PropertyInfo(alias="useTouch")] + """Actuate coordinate pointer actions as trusted touch taps instead of mouse input for mobile layouts.""" + browser: Browser browserbase_session_create_params: Annotated[ diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py index 9b9eac2e..ba6c3222 100644 --- a/tests/api_resources/test_sessions.py +++ b/tests/api_resources/test_sessions.py @@ -1115,6 +1115,7 @@ def test_method_start_with_all_params(self, client: Stagehand) -> None: session = client.sessions.start( model_name="openai/gpt-5.4-mini", act_timeout_ms=0, + use_touch=True, browser={ "cdp_url": "ws://localhost:9222", "launch_options": { @@ -2323,6 +2324,7 @@ async def test_method_start_with_all_params(self, async_client: AsyncStagehand) session = await async_client.sessions.start( model_name="openai/gpt-5.4-mini", act_timeout_ms=0, + use_touch=True, browser={ "cdp_url": "ws://localhost:9222", "launch_options": { diff --git a/tests/test_sessions_create_helper.py b/tests/test_sessions_create_helper.py index 7b5bf47f..62bf2d92 100644 --- a/tests/test_sessions_create_helper.py +++ b/tests/test_sessions_create_helper.py @@ -20,7 +20,7 @@ def test_sessions_create_returns_bound_session(respx_mock: MockRouter, client: Stagehand) -> None: session_id = "00000000-0000-0000-0000-000000000000" - respx_mock.post("/v1/sessions/start").mock( + start_route = respx_mock.post("/v1/sessions/start").mock( return_value=httpx.Response( 200, json={ @@ -37,8 +37,10 @@ def test_sessions_create_returns_bound_session(respx_mock: MockRouter, client: S ) ) - session = client.sessions.start(model_name="openai/gpt-5-nano") + session = client.sessions.start(model_name="openai/gpt-5-nano", use_touch=True) assert session.id == session_id + start_call = cast(Call, start_route.calls[0]) + assert json.loads(start_call.request.content)["useTouch"] is True session.navigate(url="https://example.com") assert navigate_route.called is True @@ -53,7 +55,7 @@ async def test_async_sessions_create_returns_bound_session( ) -> None: session_id = "00000000-0000-0000-0000-000000000000" - respx_mock.post("/v1/sessions/start").mock( + start_route = respx_mock.post("/v1/sessions/start").mock( return_value=httpx.Response( 200, json={ @@ -70,8 +72,10 @@ async def test_async_sessions_create_returns_bound_session( ) ) - session = await async_client.sessions.start(model_name="openai/gpt-5-nano") + session = await async_client.sessions.start(model_name="openai/gpt-5-nano", use_touch=True) assert session.id == session_id + start_call = cast(Call, start_route.calls[0]) + assert json.loads(start_call.request.content)["useTouch"] is True await session.navigate(url="https://example.com") assert navigate_route.called is True diff --git a/uv.lock b/uv.lock index bac119b7..91121c2e 100644 --- a/uv.lock +++ b/uv.lock @@ -1335,7 +1335,7 @@ wheels = [ [[package]] name = "stagehand" -version = "3.19.4" +version = "3.23.0" source = { editable = "." } dependencies = [ { name = "anyio", version = "4.12.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },