From d04a92742a449ee597cc68b2312e90a835f9e8b2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 10 Feb 2026 06:32:03 +0000
Subject: [PATCH 01/14] chore(internal): bump dependencies
---
requirements-dev.lock | 20 ++++++++++----------
requirements.lock | 8 ++++----
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/requirements-dev.lock b/requirements-dev.lock
index a25ec1b0..e55c751c 100644
--- a/requirements-dev.lock
+++ b/requirements-dev.lock
@@ -12,14 +12,14 @@
-e file:.
aiohappyeyeballs==2.6.1
# via aiohttp
-aiohttp==3.13.2
+aiohttp==3.13.3
# via httpx-aiohttp
# via steel-sdk
aiosignal==1.4.0
# via aiohttp
annotated-types==0.7.0
# via pydantic
-anyio==4.12.0
+anyio==4.12.1
# via httpx
# via steel-sdk
argcomplete==3.6.3
@@ -31,7 +31,7 @@ attrs==25.4.0
# via nox
backports-asyncio-runner==1.2.0
# via pytest-asyncio
-certifi==2025.11.12
+certifi==2026.1.4
# via httpcore
# via httpx
colorlog==6.10.1
@@ -61,7 +61,7 @@ httpx==0.28.1
# via httpx-aiohttp
# via respx
# via steel-sdk
-httpx-aiohttp==0.1.9
+httpx-aiohttp==0.1.12
# via steel-sdk
humanize==4.13.0
# via nox
@@ -69,7 +69,7 @@ idna==3.11
# via anyio
# via httpx
# via yarl
-importlib-metadata==8.7.0
+importlib-metadata==8.7.1
iniconfig==2.1.0
# via pytest
markdown-it-py==3.0.0
@@ -82,14 +82,14 @@ multidict==6.7.0
mypy==1.17.0
mypy-extensions==1.1.0
# via mypy
-nodeenv==1.9.1
+nodeenv==1.10.0
# via pyright
nox==2025.11.12
packaging==25.0
# via dependency-groups
# via nox
# via pytest
-pathspec==0.12.1
+pathspec==1.0.3
# via mypy
platformdirs==4.4.0
# via virtualenv
@@ -115,13 +115,13 @@ python-dateutil==2.9.0.post0
# via time-machine
respx==0.22.0
rich==14.2.0
-ruff==0.14.7
+ruff==0.14.13
six==1.17.0
# via python-dateutil
sniffio==1.3.1
# via steel-sdk
time-machine==2.19.0
-tomli==2.3.0
+tomli==2.4.0
# via dependency-groups
# via mypy
# via nox
@@ -141,7 +141,7 @@ typing-extensions==4.15.0
# via virtualenv
typing-inspection==0.4.2
# via pydantic
-virtualenv==20.35.4
+virtualenv==20.36.1
# via nox
yarl==1.22.0
# via aiohttp
diff --git a/requirements.lock b/requirements.lock
index 2ceaf4b6..b4878467 100644
--- a/requirements.lock
+++ b/requirements.lock
@@ -12,21 +12,21 @@
-e file:.
aiohappyeyeballs==2.6.1
# via aiohttp
-aiohttp==3.13.2
+aiohttp==3.13.3
# via httpx-aiohttp
# via steel-sdk
aiosignal==1.4.0
# via aiohttp
annotated-types==0.7.0
# via pydantic
-anyio==4.12.0
+anyio==4.12.1
# via httpx
# via steel-sdk
async-timeout==5.0.1
# via aiohttp
attrs==25.4.0
# via aiohttp
-certifi==2025.11.12
+certifi==2026.1.4
# via httpcore
# via httpx
distro==1.9.0
@@ -43,7 +43,7 @@ httpcore==1.0.9
httpx==0.28.1
# via httpx-aiohttp
# via steel-sdk
-httpx-aiohttp==0.1.9
+httpx-aiohttp==0.1.12
# via steel-sdk
idna==3.11
# via anyio
From 5bfdbc994392efd19eb97b366113416dddb4eb69 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 08:21:15 +0000
Subject: [PATCH 02/14] chore(internal): fix lint error on Python 3.14
---
src/steel/_utils/_compat.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/steel/_utils/_compat.py b/src/steel/_utils/_compat.py
index dd703233..2c70b299 100644
--- a/src/steel/_utils/_compat.py
+++ b/src/steel/_utils/_compat.py
@@ -26,7 +26,7 @@ def is_union(tp: Optional[Type[Any]]) -> bool:
else:
import types
- return tp is Union or tp is types.UnionType
+ return tp is Union or tp is types.UnionType # type: ignore[comparison-overlap]
def is_typeddict(tp: Type[Any]) -> bool:
From 99ec714917e3375108409099c28ce0a8efc2171e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 05:24:19 +0000
Subject: [PATCH 03/14] chore: format all `api.md` files
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 10d2c916..7b34ce9c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -69,7 +69,7 @@ format = { chain = [
# run formatting again to fix any inconsistencies when imports are stripped
"format:ruff",
]}
-"format:docs" = "python scripts/utils/ruffen-docs.py README.md api.md"
+"format:docs" = "bash -c 'python scripts/utils/ruffen-docs.py README.md $(find . -type f -name api.md)'"
"format:ruff" = "ruff format"
"lint" = { chain = [
From 20160d01b7660dc2b3856a2069d3fe3bde7ad2c0 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Feb 2026 14:19:00 +0000
Subject: [PATCH 04/14] feat(api): api update
---
.stats.yml | 4 +--
api.md | 2 +-
src/steel/resources/sessions/sessions.py | 46 ++++++++++++++++++++++--
src/steel/types/__init__.py | 1 +
src/steel/types/session_events_params.py | 18 ++++++++++
tests/api_resources/test_sessions.py | 36 ++++++++++++++-----
6 files changed, 93 insertions(+), 14 deletions(-)
create mode 100644 src/steel/types/session_events_params.py
diff --git a/.stats.yml b/.stats.yml
index 416f1d7a..3815e216 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 39
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-45efcdf3e5ccffb6e94a86be505b24b7b4ff05d8f1a2978c2a281729af68cb82.yml
-openapi_spec_hash: 9a7724672b05d44888d67b6ed0ffc7ca
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-725a0defba4d776777ef33053c239c1e41128f48fffe1dd2b27076a353ec8486.yml
+openapi_spec_hash: e02416b4dc63a92be8b82ca5fbc02d73
config_hash: dce4dea59023b0a00890fa654fbfffb4
diff --git a/api.md b/api.md
index 49ae21fe..8f08616f 100644
--- a/api.md
+++ b/api.md
@@ -71,7 +71,7 @@ Methods:
- client.sessions.list(\*\*params) -> SyncSessionsCursor[Session]
- client.sessions.computer(session_id, \*\*params) -> SessionComputerResponse
- client.sessions.context(id) -> SessionContext
-- client.sessions.events(id) -> SessionEventsResponse
+- client.sessions.events(id, \*\*params) -> SessionEventsResponse
- client.sessions.live_details(id) -> SessionLiveDetailsResponse
- client.sessions.release(id) -> SessionReleaseResponse
- client.sessions.release_all() -> SessionReleaseAllResponse
diff --git a/src/steel/resources/sessions/sessions.py b/src/steel/resources/sessions/sessions.py
index a02b81c8..572ffef9 100644
--- a/src/steel/resources/sessions/sessions.py
+++ b/src/steel/resources/sessions/sessions.py
@@ -15,7 +15,7 @@
FilesResourceWithStreamingResponse,
AsyncFilesResourceWithStreamingResponse,
)
-from ...types import session_list_params, session_create_params, session_computer_params
+from ...types import session_list_params, session_create_params, session_events_params, session_computer_params
from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from ..._utils import required_args, maybe_transform, async_maybe_transform
from .captchas import (
@@ -716,6 +716,9 @@ def events(
self,
id: str,
*,
+ compressed: bool | Omit = omit,
+ limit: int | Omit = omit,
+ pointer: str | 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,
@@ -727,6 +730,12 @@ def events(
This endpoint allows you to get the recorded session events in the RRWeb format
Args:
+ compressed: Compress the events
+
+ limit: Optional pagination limit
+
+ pointer: Pagination pointer
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -740,7 +749,18 @@ def events(
return self._get(
f"/v1/sessions/{id}/events",
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "compressed": compressed,
+ "limit": limit,
+ "pointer": pointer,
+ },
+ session_events_params.SessionEventsParams,
+ ),
),
cast_to=SessionEventsResponse,
)
@@ -1499,6 +1519,9 @@ async def events(
self,
id: str,
*,
+ compressed: bool | Omit = omit,
+ limit: int | Omit = omit,
+ pointer: str | 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,
@@ -1510,6 +1533,12 @@ async def events(
This endpoint allows you to get the recorded session events in the RRWeb format
Args:
+ compressed: Compress the events
+
+ limit: Optional pagination limit
+
+ pointer: Pagination pointer
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -1523,7 +1552,18 @@ async def events(
return await self._get(
f"/v1/sessions/{id}/events",
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "compressed": compressed,
+ "limit": limit,
+ "pointer": pointer,
+ },
+ session_events_params.SessionEventsParams,
+ ),
),
cast_to=SessionEventsResponse,
)
diff --git a/src/steel/types/__init__.py b/src/steel/types/__init__.py
index e33ce8a3..f2739660 100644
--- a/src/steel/types/__init__.py
+++ b/src/steel/types/__init__.py
@@ -19,6 +19,7 @@
from .profile_list_response import ProfileListResponse as ProfileListResponse
from .profile_update_params import ProfileUpdateParams as ProfileUpdateParams
from .session_create_params import SessionCreateParams as SessionCreateParams
+from .session_events_params import SessionEventsParams as SessionEventsParams
from .credential_list_params import CredentialListParams as CredentialListParams
from .extension_list_response import ExtensionListResponse as ExtensionListResponse
from .extension_update_params import ExtensionUpdateParams as ExtensionUpdateParams
diff --git a/src/steel/types/session_events_params.py b/src/steel/types/session_events_params.py
new file mode 100644
index 00000000..08439f70
--- /dev/null
+++ b/src/steel/types/session_events_params.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["SessionEventsParams"]
+
+
+class SessionEventsParams(TypedDict, total=False):
+ compressed: bool
+ """Compress the events"""
+
+ limit: int
+ """Optional pagination limit"""
+
+ pointer: str
+ """Pagination pointer"""
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 05d575d7..13683536 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -747,14 +747,24 @@ def test_path_params_context(self, client: Steel) -> None:
@parametrize
def test_method_events(self, client: Steel) -> None:
session = client.sessions.events(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(SessionEventsResponse, session, path=["response"])
+
+ @parametrize
+ def test_method_events_with_all_params(self, client: Steel) -> None:
+ session = client.sessions.events(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ compressed=True,
+ limit=-9007199254740991,
+ pointer="pointer",
)
assert_matches_type(SessionEventsResponse, session, path=["response"])
@parametrize
def test_raw_response_events(self, client: Steel) -> None:
response = client.sessions.with_raw_response.events(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -765,7 +775,7 @@ def test_raw_response_events(self, client: Steel) -> None:
@parametrize
def test_streaming_response_events(self, client: Steel) -> None:
with client.sessions.with_streaming_response.events(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -779,7 +789,7 @@ def test_streaming_response_events(self, client: Steel) -> None:
def test_path_params_events(self, client: Steel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
client.sessions.with_raw_response.events(
- "",
+ id="",
)
@parametrize
@@ -1608,14 +1618,24 @@ async def test_path_params_context(self, async_client: AsyncSteel) -> None:
@parametrize
async def test_method_events(self, async_client: AsyncSteel) -> None:
session = await async_client.sessions.events(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(SessionEventsResponse, session, path=["response"])
+
+ @parametrize
+ async def test_method_events_with_all_params(self, async_client: AsyncSteel) -> None:
+ session = await async_client.sessions.events(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ compressed=True,
+ limit=-9007199254740991,
+ pointer="pointer",
)
assert_matches_type(SessionEventsResponse, session, path=["response"])
@parametrize
async def test_raw_response_events(self, async_client: AsyncSteel) -> None:
response = await async_client.sessions.with_raw_response.events(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -1626,7 +1646,7 @@ async def test_raw_response_events(self, async_client: AsyncSteel) -> None:
@parametrize
async def test_streaming_response_events(self, async_client: AsyncSteel) -> None:
async with async_client.sessions.with_streaming_response.events(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1640,7 +1660,7 @@ async def test_streaming_response_events(self, async_client: AsyncSteel) -> None
async def test_path_params_events(self, async_client: AsyncSteel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
await async_client.sessions.with_raw_response.events(
- "",
+ id="",
)
@parametrize
From 98b44de2a1a0eb2f17878fe3d01a2b45d5d0ded5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Feb 2026 07:55:03 +0000
Subject: [PATCH 05/14] chore: update mock server docs
---
CONTRIBUTING.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5c571fbe..fbd86d24 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -88,8 +88,7 @@ $ pip install ./path-to-wheel-file.whl
Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
```sh
-# you will need npm installed
-$ npx prism mock path/to/your/openapi.yml
+$ ./scripts/mock
```
```sh
From 5e72d8e76a7e017a7611d87d3b49a1d7e25cd21e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Feb 2026 08:07:09 +0000
Subject: [PATCH 06/14] chore(internal): add request options to SSE classes
---
src/steel/_response.py | 3 +++
src/steel/_streaming.py | 11 ++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/steel/_response.py b/src/steel/_response.py
index 4a4b497b..db760162 100644
--- a/src/steel/_response.py
+++ b/src/steel/_response.py
@@ -152,6 +152,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
),
response=self.http_response,
client=cast(Any, self._client),
+ options=self._options,
),
)
@@ -162,6 +163,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
cast_to=extract_stream_chunk_type(self._stream_cls),
response=self.http_response,
client=cast(Any, self._client),
+ options=self._options,
),
)
@@ -175,6 +177,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
cast_to=cast_to,
response=self.http_response,
client=cast(Any, self._client),
+ options=self._options,
),
)
diff --git a/src/steel/_streaming.py b/src/steel/_streaming.py
index 3f2344fa..a5f00069 100644
--- a/src/steel/_streaming.py
+++ b/src/steel/_streaming.py
@@ -4,7 +4,7 @@
import json
import inspect
from types import TracebackType
-from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, AsyncIterator, cast
+from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast
from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable
import httpx
@@ -13,6 +13,7 @@
if TYPE_CHECKING:
from ._client import Steel, AsyncSteel
+ from ._models import FinalRequestOptions
_T = TypeVar("_T")
@@ -22,7 +23,7 @@ class Stream(Generic[_T]):
"""Provides the core interface to iterate over a synchronous stream response."""
response: httpx.Response
-
+ _options: Optional[FinalRequestOptions] = None
_decoder: SSEBytesDecoder
def __init__(
@@ -31,10 +32,12 @@ def __init__(
cast_to: type[_T],
response: httpx.Response,
client: Steel,
+ options: Optional[FinalRequestOptions] = None,
) -> None:
self.response = response
self._cast_to = cast_to
self._client = client
+ self._options = options
self._decoder = client._make_sse_decoder()
self._iterator = self.__stream__()
@@ -85,7 +88,7 @@ class AsyncStream(Generic[_T]):
"""Provides the core interface to iterate over an asynchronous stream response."""
response: httpx.Response
-
+ _options: Optional[FinalRequestOptions] = None
_decoder: SSEDecoder | SSEBytesDecoder
def __init__(
@@ -94,10 +97,12 @@ def __init__(
cast_to: type[_T],
response: httpx.Response,
client: AsyncSteel,
+ options: Optional[FinalRequestOptions] = None,
) -> None:
self.response = response
self._cast_to = cast_to
self._client = client
+ self._options = options
self._decoder = client._make_sse_decoder()
self._iterator = self.__stream__()
From 2e233ea37507adb2f05b4419ef0e8fd1932f6ba4 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Feb 2026 08:21:17 +0000
Subject: [PATCH 07/14] chore(internal): make
`test_proxy_environment_variables` more resilient
---
tests/test_client.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tests/test_client.py b/tests/test_client.py
index fe612e5a..07f1cb40 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -904,6 +904,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
+ # Delete in case our environment has this set
+ monkeypatch.delenv("HTTP_PROXY", raising=False)
client = DefaultHttpxClient()
@@ -1756,6 +1758,8 @@ async def test_get_platform(self) -> None:
async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
+ # Delete in case our environment has this set
+ monkeypatch.delenv("HTTP_PROXY", raising=False)
client = DefaultAsyncHttpxClient()
From bfcb31ebdff79c4115bc2bb6c4f7e0c48a55f469 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Feb 2026 00:23:37 +0000
Subject: [PATCH 08/14] feat(api): api update
---
.stats.yml | 4 ++--
src/steel/resources/sessions/sessions.py | 4 ++--
src/steel/types/session_events_params.py | 5 ++++-
tests/api_resources/test_sessions.py | 4 ++--
4 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 3815e216..db5d9400 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 39
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-725a0defba4d776777ef33053c239c1e41128f48fffe1dd2b27076a353ec8486.yml
-openapi_spec_hash: e02416b4dc63a92be8b82ca5fbc02d73
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-4b22ad455f8bb416a7cd29beefa7d45a3de48382232ba24503867bb6c56da90f.yml
+openapi_spec_hash: 98fd3141a41b0270cb651858bc202e78
config_hash: dce4dea59023b0a00890fa654fbfffb4
diff --git a/src/steel/resources/sessions/sessions.py b/src/steel/resources/sessions/sessions.py
index 572ffef9..611cd23c 100644
--- a/src/steel/resources/sessions/sessions.py
+++ b/src/steel/resources/sessions/sessions.py
@@ -734,7 +734,7 @@ def events(
limit: Optional pagination limit
- pointer: Pagination pointer
+ pointer: Opaque pagination token. Pass the Next-Cursor header value to get the next page.
extra_headers: Send extra headers
@@ -1537,7 +1537,7 @@ async def events(
limit: Optional pagination limit
- pointer: Pagination pointer
+ pointer: Opaque pagination token. Pass the Next-Cursor header value to get the next page.
extra_headers: Send extra headers
diff --git a/src/steel/types/session_events_params.py b/src/steel/types/session_events_params.py
index 08439f70..d66997c4 100644
--- a/src/steel/types/session_events_params.py
+++ b/src/steel/types/session_events_params.py
@@ -15,4 +15,7 @@ class SessionEventsParams(TypedDict, total=False):
"""Optional pagination limit"""
pointer: str
- """Pagination pointer"""
+ """Opaque pagination token.
+
+ Pass the Next-Cursor header value to get the next page.
+ """
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 13683536..9547c321 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -756,7 +756,7 @@ def test_method_events_with_all_params(self, client: Steel) -> None:
session = client.sessions.events(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
compressed=True,
- limit=-9007199254740991,
+ limit=1,
pointer="pointer",
)
assert_matches_type(SessionEventsResponse, session, path=["response"])
@@ -1627,7 +1627,7 @@ async def test_method_events_with_all_params(self, async_client: AsyncSteel) ->
session = await async_client.sessions.events(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
compressed=True,
- limit=-9007199254740991,
+ limit=1,
pointer="pointer",
)
assert_matches_type(SessionEventsResponse, session, path=["response"])
From 8b312f41858a4abf129a5e5da1ed75d5cddffe16 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Feb 2026 07:59:11 +0000
Subject: [PATCH 09/14] chore(internal): make
`test_proxy_environment_variables` more resilient to env
---
tests/test_client.py | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/tests/test_client.py b/tests/test_client.py
index 07f1cb40..410bcac6 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -904,8 +904,14 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
- # Delete in case our environment has this set
+ # Delete in case our environment has any proxy env vars set
monkeypatch.delenv("HTTP_PROXY", raising=False)
+ monkeypatch.delenv("ALL_PROXY", raising=False)
+ monkeypatch.delenv("NO_PROXY", raising=False)
+ monkeypatch.delenv("http_proxy", raising=False)
+ monkeypatch.delenv("https_proxy", raising=False)
+ monkeypatch.delenv("all_proxy", raising=False)
+ monkeypatch.delenv("no_proxy", raising=False)
client = DefaultHttpxClient()
@@ -1758,8 +1764,14 @@ async def test_get_platform(self) -> None:
async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
- # Delete in case our environment has this set
+ # Delete in case our environment has any proxy env vars set
monkeypatch.delenv("HTTP_PROXY", raising=False)
+ monkeypatch.delenv("ALL_PROXY", raising=False)
+ monkeypatch.delenv("NO_PROXY", raising=False)
+ monkeypatch.delenv("http_proxy", raising=False)
+ monkeypatch.delenv("https_proxy", raising=False)
+ monkeypatch.delenv("all_proxy", raising=False)
+ monkeypatch.delenv("no_proxy", raising=False)
client = DefaultAsyncHttpxClient()
From faf3551f91a527bada3b902550742dca0668d91f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 6 Mar 2026 14:05:10 +0000
Subject: [PATCH 10/14] chore(test): do not count install time for mock server
timeout
---
scripts/mock | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/scripts/mock b/scripts/mock
index 0b28f6ea..bcf3b392 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -21,11 +21,22 @@ echo "==> Starting mock server with URL ${URL}"
# Run prism mock on the given spec
if [ "$1" == "--daemon" ]; then
+ # Pre-install the package so the download doesn't eat into the startup timeout
+ npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version
+
npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log &
- # Wait for server to come online
+ # Wait for server to come online (max 30s)
echo -n "Waiting for server"
+ attempts=0
while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do
+ attempts=$((attempts + 1))
+ if [ "$attempts" -ge 300 ]; then
+ echo
+ echo "Timed out waiting for Prism server to start"
+ cat .prism.log
+ exit 1
+ fi
echo -n "."
sleep 0.1
done
From 54e6339015586e3ffe196c459385cbc2dd6eb94a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 7 Mar 2026 19:22:28 +0000
Subject: [PATCH 11/14] chore(ci): skip uploading artifacts on
stainless-internal branches
---
.github/workflows/ci.yml | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8ba6b37d..97f05b2a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -61,14 +61,18 @@ jobs:
run: rye build
- name: Get GitHub OIDC Token
- if: github.repository == 'stainless-sdks/steel-python'
+ if: |-
+ github.repository == 'stainless-sdks/steel-python' &&
+ !startsWith(github.ref, 'refs/heads/stl/')
id: github-oidc
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());
- name: Upload tarball
- if: github.repository == 'stainless-sdks/steel-python'
+ if: |-
+ github.repository == 'stainless-sdks/steel-python' &&
+ !startsWith(github.ref, 'refs/heads/stl/')
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
From 3af093a33381b2436287bdeb87ff0b3e0f997385 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 7 Mar 2026 19:24:39 +0000
Subject: [PATCH 12/14] chore: update placeholder string
---
tests/api_resources/sessions/test_files.py | 20 ++++++------
tests/api_resources/test_extensions.py | 8 ++---
tests/api_resources/test_files.py | 16 +++++-----
tests/api_resources/test_profiles.py | 36 +++++++++++-----------
4 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/tests/api_resources/sessions/test_files.py b/tests/api_resources/sessions/test_files.py
index be2dbb03..ed641c70 100644
--- a/tests/api_resources/sessions/test_files.py
+++ b/tests/api_resources/sessions/test_files.py
@@ -263,7 +263,7 @@ def test_path_params_download_archive(self, client: Steel) -> None:
def test_method_upload(self, client: Steel) -> None:
file = client.sessions.files.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
)
assert_matches_type(File, file, path=["response"])
@@ -271,7 +271,7 @@ def test_method_upload(self, client: Steel) -> None:
def test_method_upload_with_all_params(self, client: Steel) -> None:
file = client.sessions.files.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
path="path",
)
assert_matches_type(File, file, path=["response"])
@@ -280,7 +280,7 @@ def test_method_upload_with_all_params(self, client: Steel) -> None:
def test_raw_response_upload(self, client: Steel) -> None:
response = client.sessions.files.with_raw_response.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
)
assert response.is_closed is True
@@ -292,7 +292,7 @@ def test_raw_response_upload(self, client: Steel) -> None:
def test_streaming_response_upload(self, client: Steel) -> None:
with client.sessions.files.with_streaming_response.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -307,7 +307,7 @@ def test_path_params_upload(self, client: Steel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
client.sessions.files.with_raw_response.upload(
session_id="",
- file=b"raw file contents",
+ file=b"Example data",
)
@@ -554,7 +554,7 @@ async def test_path_params_download_archive(self, async_client: AsyncSteel) -> N
async def test_method_upload(self, async_client: AsyncSteel) -> None:
file = await async_client.sessions.files.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
)
assert_matches_type(File, file, path=["response"])
@@ -562,7 +562,7 @@ async def test_method_upload(self, async_client: AsyncSteel) -> None:
async def test_method_upload_with_all_params(self, async_client: AsyncSteel) -> None:
file = await async_client.sessions.files.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
path="path",
)
assert_matches_type(File, file, path=["response"])
@@ -571,7 +571,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncSteel) ->
async def test_raw_response_upload(self, async_client: AsyncSteel) -> None:
response = await async_client.sessions.files.with_raw_response.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
)
assert response.is_closed is True
@@ -583,7 +583,7 @@ async def test_raw_response_upload(self, async_client: AsyncSteel) -> None:
async def test_streaming_response_upload(self, async_client: AsyncSteel) -> None:
async with async_client.sessions.files.with_streaming_response.upload(
session_id="sessionId",
- file=b"raw file contents",
+ file=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -598,5 +598,5 @@ async def test_path_params_upload(self, async_client: AsyncSteel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
await async_client.sessions.files.with_raw_response.upload(
session_id="",
- file=b"raw file contents",
+ file=b"Example data",
)
diff --git a/tests/api_resources/test_extensions.py b/tests/api_resources/test_extensions.py
index b996a46b..e9ceafd5 100644
--- a/tests/api_resources/test_extensions.py
+++ b/tests/api_resources/test_extensions.py
@@ -34,7 +34,7 @@ def test_method_update(self, client: Steel) -> None:
def test_method_update_with_all_params(self, client: Steel) -> None:
extension = client.extensions.update(
extension_id="extensionId",
- file=b"raw file contents",
+ file=b"Example data",
url="https://example.com",
)
assert_matches_type(ExtensionUpdateResponse, extension, path=["response"])
@@ -204,7 +204,7 @@ def test_method_upload(self, client: Steel) -> None:
@parametrize
def test_method_upload_with_all_params(self, client: Steel) -> None:
extension = client.extensions.upload(
- file=b"raw file contents",
+ file=b"Example data",
url="https://example.com",
)
assert_matches_type(ExtensionUploadResponse, extension, path=["response"])
@@ -246,7 +246,7 @@ async def test_method_update(self, async_client: AsyncSteel) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncSteel) -> None:
extension = await async_client.extensions.update(
extension_id="extensionId",
- file=b"raw file contents",
+ file=b"Example data",
url="https://example.com",
)
assert_matches_type(ExtensionUpdateResponse, extension, path=["response"])
@@ -416,7 +416,7 @@ async def test_method_upload(self, async_client: AsyncSteel) -> None:
@parametrize
async def test_method_upload_with_all_params(self, async_client: AsyncSteel) -> None:
extension = await async_client.extensions.upload(
- file=b"raw file contents",
+ file=b"Example data",
url="https://example.com",
)
assert_matches_type(ExtensionUploadResponse, extension, path=["response"])
diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py
index 5ca440d0..efcb9da6 100644
--- a/tests/api_resources/test_files.py
+++ b/tests/api_resources/test_files.py
@@ -141,14 +141,14 @@ def test_path_params_download(self, client: Steel) -> None:
@parametrize
def test_method_upload(self, client: Steel) -> None:
file = client.files.upload(
- file=b"raw file contents",
+ file=b"Example data",
)
assert_matches_type(File, file, path=["response"])
@parametrize
def test_method_upload_with_all_params(self, client: Steel) -> None:
file = client.files.upload(
- file=b"raw file contents",
+ file=b"Example data",
path="path",
)
assert_matches_type(File, file, path=["response"])
@@ -156,7 +156,7 @@ def test_method_upload_with_all_params(self, client: Steel) -> None:
@parametrize
def test_raw_response_upload(self, client: Steel) -> None:
response = client.files.with_raw_response.upload(
- file=b"raw file contents",
+ file=b"Example data",
)
assert response.is_closed is True
@@ -167,7 +167,7 @@ def test_raw_response_upload(self, client: Steel) -> None:
@parametrize
def test_streaming_response_upload(self, client: Steel) -> None:
with client.files.with_streaming_response.upload(
- file=b"raw file contents",
+ file=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -299,14 +299,14 @@ async def test_path_params_download(self, async_client: AsyncSteel) -> None:
@parametrize
async def test_method_upload(self, async_client: AsyncSteel) -> None:
file = await async_client.files.upload(
- file=b"raw file contents",
+ file=b"Example data",
)
assert_matches_type(File, file, path=["response"])
@parametrize
async def test_method_upload_with_all_params(self, async_client: AsyncSteel) -> None:
file = await async_client.files.upload(
- file=b"raw file contents",
+ file=b"Example data",
path="path",
)
assert_matches_type(File, file, path=["response"])
@@ -314,7 +314,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncSteel) ->
@parametrize
async def test_raw_response_upload(self, async_client: AsyncSteel) -> None:
response = await async_client.files.with_raw_response.upload(
- file=b"raw file contents",
+ file=b"Example data",
)
assert response.is_closed is True
@@ -325,7 +325,7 @@ async def test_raw_response_upload(self, async_client: AsyncSteel) -> None:
@parametrize
async def test_streaming_response_upload(self, async_client: AsyncSteel) -> None:
async with async_client.files.with_streaming_response.upload(
- file=b"raw file contents",
+ file=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_profiles.py b/tests/api_resources/test_profiles.py
index 24a3cd08..52324e1a 100644
--- a/tests/api_resources/test_profiles.py
+++ b/tests/api_resources/test_profiles.py
@@ -25,14 +25,14 @@ class TestProfiles:
@parametrize
def test_method_create(self, client: Steel) -> None:
profile = client.profiles.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert_matches_type(ProfileCreateResponse, profile, path=["response"])
@parametrize
def test_method_create_with_all_params(self, client: Steel) -> None:
profile = client.profiles.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
dimensions={
"height": 0,
"width": 0,
@@ -45,7 +45,7 @@ def test_method_create_with_all_params(self, client: Steel) -> None:
@parametrize
def test_raw_response_create(self, client: Steel) -> None:
response = client.profiles.with_raw_response.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert response.is_closed is True
@@ -56,7 +56,7 @@ def test_raw_response_create(self, client: Steel) -> None:
@parametrize
def test_streaming_response_create(self, client: Steel) -> None:
with client.profiles.with_streaming_response.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -70,7 +70,7 @@ def test_streaming_response_create(self, client: Steel) -> None:
def test_method_update(self, client: Steel) -> None:
profile = client.profiles.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert_matches_type(ProfileUpdateResponse, profile, path=["response"])
@@ -78,7 +78,7 @@ def test_method_update(self, client: Steel) -> None:
def test_method_update_with_all_params(self, client: Steel) -> None:
profile = client.profiles.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
dimensions={
"height": 0,
"width": 0,
@@ -92,7 +92,7 @@ def test_method_update_with_all_params(self, client: Steel) -> None:
def test_raw_response_update(self, client: Steel) -> None:
response = client.profiles.with_raw_response.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert response.is_closed is True
@@ -104,7 +104,7 @@ def test_raw_response_update(self, client: Steel) -> None:
def test_streaming_response_update(self, client: Steel) -> None:
with client.profiles.with_streaming_response.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -119,7 +119,7 @@ def test_path_params_update(self, client: Steel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
client.profiles.with_raw_response.update(
id="",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
@parametrize
@@ -194,14 +194,14 @@ class TestAsyncProfiles:
@parametrize
async def test_method_create(self, async_client: AsyncSteel) -> None:
profile = await async_client.profiles.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert_matches_type(ProfileCreateResponse, profile, path=["response"])
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncSteel) -> None:
profile = await async_client.profiles.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
dimensions={
"height": 0,
"width": 0,
@@ -214,7 +214,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncSteel) ->
@parametrize
async def test_raw_response_create(self, async_client: AsyncSteel) -> None:
response = await async_client.profiles.with_raw_response.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert response.is_closed is True
@@ -225,7 +225,7 @@ async def test_raw_response_create(self, async_client: AsyncSteel) -> None:
@parametrize
async def test_streaming_response_create(self, async_client: AsyncSteel) -> None:
async with async_client.profiles.with_streaming_response.create(
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -239,7 +239,7 @@ async def test_streaming_response_create(self, async_client: AsyncSteel) -> None
async def test_method_update(self, async_client: AsyncSteel) -> None:
profile = await async_client.profiles.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert_matches_type(ProfileUpdateResponse, profile, path=["response"])
@@ -247,7 +247,7 @@ async def test_method_update(self, async_client: AsyncSteel) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncSteel) -> None:
profile = await async_client.profiles.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
dimensions={
"height": 0,
"width": 0,
@@ -261,7 +261,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncSteel) ->
async def test_raw_response_update(self, async_client: AsyncSteel) -> None:
response = await async_client.profiles.with_raw_response.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
assert response.is_closed is True
@@ -273,7 +273,7 @@ async def test_raw_response_update(self, async_client: AsyncSteel) -> None:
async def test_streaming_response_update(self, async_client: AsyncSteel) -> None:
async with async_client.profiles.with_streaming_response.update(
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -288,7 +288,7 @@ async def test_path_params_update(self, async_client: AsyncSteel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
await async_client.profiles.with_raw_response.update(
id="",
- user_data_dir=b"raw file contents",
+ user_data_dir=b"Example data",
)
@parametrize
From b341bdb0c251b50c85d862b77bb23df08562186b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 16 Mar 2026 06:22:03 +0000
Subject: [PATCH 13/14] feat(api): api update
---
.stats.yml | 4 ++--
src/steel/resources/sessions/sessions.py | 8 ++++++++
src/steel/types/session_create_params.py | 3 +++
src/steel/types/sessionslist.py | 7 +++++--
tests/api_resources/test_sessions.py | 2 ++
5 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index db5d9400..35acfccf 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 39
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-4b22ad455f8bb416a7cd29beefa7d45a3de48382232ba24503867bb6c56da90f.yml
-openapi_spec_hash: 98fd3141a41b0270cb651858bc202e78
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nen-labs%2Fsteel-f51ce05f6128dcdd6b500492869910d3a43737c66d0bc13c3f2e67f42362605c.yml
+openapi_spec_hash: c573fb6f26d5fb14eaf92e0a107323ec
config_hash: dce4dea59023b0a00890fa654fbfffb4
diff --git a/src/steel/resources/sessions/sessions.py b/src/steel/resources/sessions/sessions.py
index 611cd23c..d54ca834 100644
--- a/src/steel/resources/sessions/sessions.py
+++ b/src/steel/resources/sessions/sessions.py
@@ -85,6 +85,7 @@ def create(
debug_config: session_create_params.DebugConfig | Omit = omit,
device_config: session_create_params.DeviceConfig | Omit = omit,
dimensions: session_create_params.Dimensions | Omit = omit,
+ experimental_features: SequenceNotStr[str] | Omit = omit,
extension_ids: SequenceNotStr[str] | Omit = omit,
headless: bool | Omit = omit,
is_selenium: bool | Omit = omit,
@@ -126,6 +127,8 @@ def create(
dimensions: Viewport and browser window dimensions for the session
+ experimental_features: Enable experimental features for the session.
+
extension_ids: Array of extension IDs to install in the session. Use ['all_ext'] to install all
uploaded extensions.
@@ -183,6 +186,7 @@ def create(
"debug_config": debug_config,
"device_config": device_config,
"dimensions": dimensions,
+ "experimental_features": experimental_features,
"extension_ids": extension_ids,
"headless": headless,
"is_selenium": is_selenium,
@@ -888,6 +892,7 @@ async def create(
debug_config: session_create_params.DebugConfig | Omit = omit,
device_config: session_create_params.DeviceConfig | Omit = omit,
dimensions: session_create_params.Dimensions | Omit = omit,
+ experimental_features: SequenceNotStr[str] | Omit = omit,
extension_ids: SequenceNotStr[str] | Omit = omit,
headless: bool | Omit = omit,
is_selenium: bool | Omit = omit,
@@ -929,6 +934,8 @@ async def create(
dimensions: Viewport and browser window dimensions for the session
+ experimental_features: Enable experimental features for the session.
+
extension_ids: Array of extension IDs to install in the session. Use ['all_ext'] to install all
uploaded extensions.
@@ -986,6 +993,7 @@ async def create(
"debug_config": debug_config,
"device_config": device_config,
"dimensions": dimensions,
+ "experimental_features": experimental_features,
"extension_ids": extension_ids,
"headless": headless,
"is_selenium": is_selenium,
diff --git a/src/steel/types/session_create_params.py b/src/steel/types/session_create_params.py
index b98d7f3f..cfb5d8fa 100644
--- a/src/steel/types/session_create_params.py
+++ b/src/steel/types/session_create_params.py
@@ -58,6 +58,9 @@ class SessionCreateParams(TypedDict, total=False):
dimensions: Dimensions
"""Viewport and browser window dimensions for the session"""
+ experimental_features: Annotated[SequenceNotStr[str], PropertyInfo(alias="experimentalFeatures")]
+ """Enable experimental features for the session."""
+
extension_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="extensionIds")]
"""Array of extension IDs to install in the session.
diff --git a/src/steel/types/sessionslist.py b/src/steel/types/sessionslist.py
index 05604e7e..58dfd383 100644
--- a/src/steel/types/sessionslist.py
+++ b/src/steel/types/sessionslist.py
@@ -177,5 +177,8 @@ class Sessionslist(BaseModel):
sessions: List[Session]
"""List of browser sessions"""
- total_count: int = FieldInfo(alias="totalCount")
- """Total number of sessions matching the query"""
+ total_count: Optional[int] = FieldInfo(alias="totalCount", default=None)
+ """Total number of sessions matching the query.
+
+ Only included for filtered queries (e.g. status=live).
+ """
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 9547c321..9fabc926 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -52,6 +52,7 @@ def test_method_create_with_all_params(self, client: Steel) -> None:
"height": -9007199254740991,
"width": -9007199254740991,
},
+ experimental_features=["string"],
extension_ids=["string"],
headless=True,
is_selenium=True,
@@ -923,6 +924,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncSteel) ->
"height": -9007199254740991,
"width": -9007199254740991,
},
+ experimental_features=["string"],
extension_ids=["string"],
headless=True,
is_selenium=True,
From 1da6957ab286a943397d2f71033c929acde19780 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 16 Mar 2026 06:22:48 +0000
Subject: [PATCH 14/14] release: 0.17.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 24 ++++++++++++++++++++++++
pyproject.toml | 2 +-
src/steel/_version.py | 2 +-
4 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index b4e9013b..6db19b95 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.16.0"
+ ".": "0.17.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f1805a8..ab379643 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,29 @@
# Changelog
+## 0.17.0 (2026-03-16)
+
+Full Changelog: [v0.16.0...v0.17.0](https://github.com/steel-dev/steel-python/compare/v0.16.0...v0.17.0)
+
+### Features
+
+* **api:** api update ([b341bdb](https://github.com/steel-dev/steel-python/commit/b341bdb0c251b50c85d862b77bb23df08562186b))
+* **api:** api update ([bfcb31e](https://github.com/steel-dev/steel-python/commit/bfcb31ebdff79c4115bc2bb6c4f7e0c48a55f469))
+* **api:** api update ([20160d0](https://github.com/steel-dev/steel-python/commit/20160d01b7660dc2b3856a2069d3fe3bde7ad2c0))
+
+
+### Chores
+
+* **ci:** skip uploading artifacts on stainless-internal branches ([54e6339](https://github.com/steel-dev/steel-python/commit/54e6339015586e3ffe196c459385cbc2dd6eb94a))
+* format all `api.md` files ([99ec714](https://github.com/steel-dev/steel-python/commit/99ec714917e3375108409099c28ce0a8efc2171e))
+* **internal:** add request options to SSE classes ([5e72d8e](https://github.com/steel-dev/steel-python/commit/5e72d8e76a7e017a7611d87d3b49a1d7e25cd21e))
+* **internal:** bump dependencies ([d04a927](https://github.com/steel-dev/steel-python/commit/d04a92742a449ee597cc68b2312e90a835f9e8b2))
+* **internal:** fix lint error on Python 3.14 ([5bfdbc9](https://github.com/steel-dev/steel-python/commit/5bfdbc994392efd19eb97b366113416dddb4eb69))
+* **internal:** make `test_proxy_environment_variables` more resilient ([2e233ea](https://github.com/steel-dev/steel-python/commit/2e233ea37507adb2f05b4419ef0e8fd1932f6ba4))
+* **internal:** make `test_proxy_environment_variables` more resilient to env ([8b312f4](https://github.com/steel-dev/steel-python/commit/8b312f41858a4abf129a5e5da1ed75d5cddffe16))
+* **test:** do not count install time for mock server timeout ([faf3551](https://github.com/steel-dev/steel-python/commit/faf3551f91a527bada3b902550742dca0668d91f))
+* update mock server docs ([98b44de](https://github.com/steel-dev/steel-python/commit/98b44de2a1a0eb2f17878fe3d01a2b45d5d0ded5))
+* update placeholder string ([3af093a](https://github.com/steel-dev/steel-python/commit/3af093a33381b2436287bdeb87ff0b3e0f997385))
+
## 0.16.0 (2026-02-06)
Full Changelog: [v0.15.0...v0.16.0](https://github.com/steel-dev/steel-python/compare/v0.15.0...v0.16.0)
diff --git a/pyproject.toml b/pyproject.toml
index 7b34ce9c..8219a00b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "steel-sdk"
-version = "0.16.0"
+version = "0.17.0"
description = "The official Python library for the steel API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/steel/_version.py b/src/steel/_version.py
index b8580980..06fdcfc6 100644
--- a/src/steel/_version.py
+++ b/src/steel/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "steel"
-__version__ = "0.16.0" # x-release-please-version
+__version__ = "0.17.0" # x-release-please-version