From 4f1248dfb1bf79194f65854a6fcd6a0d53433ba1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 22:55:54 +0000 Subject: [PATCH 1/6] feat: [CORE-1928][apps/api] Add `PENDING` as a valid session state --- .stats.yml | 4 ++-- src/browserbase/resources/sessions/sessions.py | 4 ++-- src/browserbase/types/session.py | 2 +- src/browserbase/types/session_list_params.py | 2 +- tests/api_resources/test_sessions.py | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index bf216680..cfabd9dc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-921d3c61c7aa06269f74bee63cee993597944f913429caa2aa2e00dd51fab60f.yml -openapi_spec_hash: d35b9613c41bf172fa2b28aceef10b39 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-592ec7680e78e2cb6f33a051cb82c208b93c174b7458186efb54fca8254312d1.yml +openapi_spec_hash: 77b58db061531c44f27d9bd5fbff9e93 config_hash: cf04ecfb8dad5fbd8b85be25d6e9ec55 diff --git a/src/browserbase/resources/sessions/sessions.py b/src/browserbase/resources/sessions/sessions.py index 18bb0a73..ce3de98f 100644 --- a/src/browserbase/resources/sessions/sessions.py +++ b/src/browserbase/resources/sessions/sessions.py @@ -255,7 +255,7 @@ def list( self, *, q: str | Omit = omit, - status: Literal["RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] | Omit = omit, + status: Literal["PENDING", "RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -527,7 +527,7 @@ async def list( self, *, q: str | Omit = omit, - status: Literal["RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] | Omit = omit, + status: Literal["PENDING", "RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/browserbase/types/session.py b/src/browserbase/types/session.py index e983baaa..eac6a815 100644 --- a/src/browserbase/types/session.py +++ b/src/browserbase/types/session.py @@ -32,7 +32,7 @@ class Session(BaseModel): started_at: datetime = FieldInfo(alias="startedAt") - status: Literal["RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] + status: Literal["PENDING", "RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] updated_at: datetime = FieldInfo(alias="updatedAt") diff --git a/src/browserbase/types/session_list_params.py b/src/browserbase/types/session_list_params.py index 54b0a05c..c21b98e1 100644 --- a/src/browserbase/types/session_list_params.py +++ b/src/browserbase/types/session_list_params.py @@ -16,4 +16,4 @@ class SessionListParams(TypedDict, total=False): for the schema of this query. """ - status: Literal["RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] + status: Literal["PENDING", "RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py index eb07d3fc..78f99ceb 100644 --- a/tests/api_resources/test_sessions.py +++ b/tests/api_resources/test_sessions.py @@ -189,7 +189,7 @@ def test_method_list(self, client: Browserbase) -> None: def test_method_list_with_all_params(self, client: Browserbase) -> None: session = client.sessions.list( q="q", - status="RUNNING", + status="PENDING", ) assert_matches_type(SessionListResponse, session, path=["response"]) @@ -423,7 +423,7 @@ async def test_method_list(self, async_client: AsyncBrowserbase) -> None: async def test_method_list_with_all_params(self, async_client: AsyncBrowserbase) -> None: session = await async_client.sessions.list( q="q", - status="RUNNING", + status="PENDING", ) assert_matches_type(SessionListResponse, session, path=["response"]) From 953fd3ecd54a7ffc2ee390eac67f2063df89b8e9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 02:15:01 +0000 Subject: [PATCH 2/6] fix(client): preserve hardcoded query params when merging with user params --- src/browserbase/_base_client.py | 4 +++ tests/test_client.py | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/browserbase/_base_client.py b/src/browserbase/_base_client.py index 5bc9823d..bd88f594 100644 --- a/src/browserbase/_base_client.py +++ b/src/browserbase/_base_client.py @@ -540,6 +540,10 @@ def _build_request( files = cast(HttpxRequestFiles, ForceMultipartDict()) prepared_url = self._prepare_url(options.url) + # preserve hard-coded query params from the url + if params and prepared_url.query: + params = {**dict(prepared_url.params.items()), **params} + prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0]) if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} diff --git a/tests/test_client.py b/tests/test_client.py index 1d0d68b3..95ae8e03 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -429,6 +429,30 @@ def test_default_query_option(self) -> None: client.close() + def test_hardcoded_query_params_in_url(self, client: Browserbase) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Browserbase) -> None: request = client._build_request( FinalRequestOptions( @@ -1330,6 +1354,30 @@ async def test_default_query_option(self) -> None: await client.close() + async def test_hardcoded_query_params_in_url(self, async_client: AsyncBrowserbase) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Browserbase) -> None: request = client._build_request( FinalRequestOptions( From 3072323d083006d81ac0c2b0051665223da40cf1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:22:45 +0000 Subject: [PATCH 3/6] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index cfabd9dc..c754d3fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-592ec7680e78e2cb6f33a051cb82c208b93c174b7458186efb54fca8254312d1.yml -openapi_spec_hash: 77b58db061531c44f27d9bd5fbff9e93 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-a4cf3ac2380d1e1625bac730a8d396960f0d12599ad630355c38b33eeb2ef10a.yml +openapi_spec_hash: 79afe4d9341a697c9277596db045155b config_hash: cf04ecfb8dad5fbd8b85be25d6e9ec55 From 98127af2533a91e1adbc5244f4de22efa83b516c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 23:15:46 +0000 Subject: [PATCH 4/6] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c754d3fa..b1784cf2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-a4cf3ac2380d1e1625bac730a8d396960f0d12599ad630355c38b33eeb2ef10a.yml -openapi_spec_hash: 79afe4d9341a697c9277596db045155b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-3683b291883198719787c333144da6650b6c287db400e0b21f54797f6e986a24.yml +openapi_spec_hash: 4da0b34a056487d20ed56a3b0b1c078e config_hash: cf04ecfb8dad5fbd8b85be25d6e9ec55 From a83735708037eec6cb4807e4220ca7452b5b6503 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 02:38:14 +0000 Subject: [PATCH 5/6] fix: ensure file data are only sent as 1 parameter --- src/browserbase/_utils/_utils.py | 5 +++-- tests/test_extract_files.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/browserbase/_utils/_utils.py b/src/browserbase/_utils/_utils.py index eec7f4a1..63b8cd60 100644 --- a/src/browserbase/_utils/_utils.py +++ b/src/browserbase/_utils/_utils.py @@ -86,8 +86,9 @@ def _extract_items( index += 1 if is_dict(obj): try: - # We are at the last entry in the path so we must remove the field - if (len(path)) == index: + # Remove the field if there are no more dict keys in the path, + # only "" traversal markers or end. + if all(p == "" for p in path[index:]): item = obj.pop(key) else: item = obj[key] diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 3c0fcb36..cd614d03 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -35,6 +35,15 @@ def test_multiple_files() -> None: assert query == {"documents": [{}, {}]} +def test_top_level_file_array() -> None: + query = {"files": [b"file one", b"file two"], "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [ + ("files[]", b"file one"), + ("files[]", b"file two"), + ] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [ From 3bdcaa726a8ec5efaffccec5fa4e5fde5c348d91 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 02:38:28 +0000 Subject: [PATCH 6/6] release: 1.9.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 14 ++++++++++++++ pyproject.toml | 2 +- src/browserbase/_version.py | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c523ce19..c3c95522 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.8.0" + ".": "1.9.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a2dbc4d..763d2eeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 1.9.0 (2026-04-11) + +Full Changelog: [v1.8.0...v1.9.0](https://github.com/browserbase/sdk-python/compare/v1.8.0...v1.9.0) + +### Features + +* [CORE-1928][apps/api] Add `PENDING` as a valid session state ([4f1248d](https://github.com/browserbase/sdk-python/commit/4f1248dfb1bf79194f65854a6fcd6a0d53433ba1)) + + +### Bug Fixes + +* **client:** preserve hardcoded query params when merging with user params ([953fd3e](https://github.com/browserbase/sdk-python/commit/953fd3ecd54a7ffc2ee390eac67f2063df89b8e9)) +* ensure file data are only sent as 1 parameter ([a837357](https://github.com/browserbase/sdk-python/commit/a83735708037eec6cb4807e4220ca7452b5b6503)) + ## 1.8.0 (2026-04-06) Full Changelog: [v1.7.0...v1.8.0](https://github.com/browserbase/sdk-python/compare/v1.7.0...v1.8.0) diff --git a/pyproject.toml b/pyproject.toml index e39927c3..bc5e136d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "browserbase" -version = "1.8.0" +version = "1.9.0" description = "The official Python library for the Browserbase API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/browserbase/_version.py b/src/browserbase/_version.py index 10594de4..eaa01ae1 100644 --- a/src/browserbase/_version.py +++ b/src/browserbase/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "browserbase" -__version__ = "1.8.0" # x-release-please-version +__version__ = "1.9.0" # x-release-please-version