Skip to content
Open
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.69.0"
".": "0.70.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 120
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-cde481b2f320ce48f83db84ae96226b0e7568146c9387c4fefebf286ecb0dd0a.yml
openapi_spec_hash: 6bd86d767290fcd7e2a6aae26dff5417
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ab4e7c50c41fefd891648fa84ba0258986f192ba1bde9f42cbdf487f64c4cc27.yml
openapi_spec_hash: b4bcd6557f7045ecff30b01e02d28ac5
config_hash: 03c7e57f268c750e2415831662e95969
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.70.0 (2026-06-22)

Full Changelog: [v0.69.0...v0.70.0](https://github.com/kernel/kernel-python-sdk/compare/v0.69.0...v0.70.0)

### Features

* Align browser-pool timeout/viewport/fill-rate contract with implementation; reject save_changes on update ([5fdc97b](https://github.com/kernel/kernel-python-sdk/commit/5fdc97b27bdd92cb6f91f1162c1a5827e4a6a172))

## 0.69.0 (2026-06-18)

Full Changelog: [v0.68.0...v0.69.0](https://github.com/kernel/kernel-python-sdk/compare/v0.68.0...v0.69.0)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "kernel"
version = "0.69.0"
version = "0.70.0"
description = "The official Python library for the kernel API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "kernel"
__version__ = "0.69.0" # x-release-please-version
__version__ = "0.70.0" # x-release-please-version
24 changes: 16 additions & 8 deletions src/kernel/resources/browser_pools.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ def create(

extensions: List of browser extensions to load into the session. Provide each by id or name.

fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10%.
fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for
most organizations but can be raised per-organization, so only the lower bound
is enforced here.

headless: If true, launches the browser using a headless image. Defaults to false.

Expand All @@ -122,7 +124,7 @@ def create(
mechanisms.

timeout_seconds: Default idle timeout in seconds for browsers acquired from this pool before they
are destroyed. Defaults to 600 seconds if not specified
are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).

viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
image defaults apply (1920x1080@25). For GPU images, the default is
Expand Down Expand Up @@ -243,7 +245,9 @@ def update(

extensions: List of browser extensions to load into the session. Provide each by id or name.

fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10%.
fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for
most organizations but can be raised per-organization, so only the lower bound
is enforced here.

headless: If true, launches the browser using a headless image. Defaults to false.

Expand Down Expand Up @@ -273,7 +277,7 @@ def update(
mechanisms.

timeout_seconds: Default idle timeout in seconds for browsers acquired from this pool before they
are destroyed. Defaults to 600 seconds if not specified
are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).

viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
image defaults apply (1920x1080@25). For GPU images, the default is
Expand Down Expand Up @@ -621,7 +625,9 @@ async def create(

extensions: List of browser extensions to load into the session. Provide each by id or name.

fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10%.
fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for
most organizations but can be raised per-organization, so only the lower bound
is enforced here.

headless: If true, launches the browser using a headless image. Defaults to false.

Expand All @@ -647,7 +653,7 @@ async def create(
mechanisms.

timeout_seconds: Default idle timeout in seconds for browsers acquired from this pool before they
are destroyed. Defaults to 600 seconds if not specified
are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).

viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
image defaults apply (1920x1080@25). For GPU images, the default is
Expand Down Expand Up @@ -768,7 +774,9 @@ async def update(

extensions: List of browser extensions to load into the session. Provide each by id or name.

fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10%.
fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for
most organizations but can be raised per-organization, so only the lower bound
is enforced here.

headless: If true, launches the browser using a headless image. Defaults to false.

Expand Down Expand Up @@ -798,7 +806,7 @@ async def update(
mechanisms.

timeout_seconds: Default idle timeout in seconds for browsers acquired from this pool before they
are destroyed. Defaults to 600 seconds if not specified
are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).

viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
image defaults apply (1920x1080@25). For GPU images, the default is
Expand Down
8 changes: 6 additions & 2 deletions src/kernel/types/browser_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ class BrowserPoolConfig(BaseModel):
"""

fill_rate_per_minute: Optional[int] = None
"""Percentage of the pool to fill per minute. Defaults to 10%."""
"""Percentage of the pool to fill per minute.

Defaults to 10. The cap is 25 for most organizations but can be raised
per-organization, so only the lower bound is enforced here.
"""

headless: Optional[bool] = None
"""If true, launches the browser using a headless image. Defaults to false."""
Expand Down Expand Up @@ -81,7 +85,7 @@ class BrowserPoolConfig(BaseModel):
timeout_seconds: Optional[int] = None
"""
Default idle timeout in seconds for browsers acquired from this pool before they
are destroyed. Defaults to 600 seconds if not specified
are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).
"""

viewport: Optional[BrowserViewport] = None
Expand Down
8 changes: 6 additions & 2 deletions src/kernel/types/browser_pool_create_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ class BrowserPoolCreateParams(TypedDict, total=False):
"""

fill_rate_per_minute: int
"""Percentage of the pool to fill per minute. Defaults to 10%."""
"""Percentage of the pool to fill per minute.

Defaults to 10. The cap is 25 for most organizations but can be raised
per-organization, so only the lower bound is enforced here.
"""

headless: bool
"""If true, launches the browser using a headless image. Defaults to false."""
Expand Down Expand Up @@ -80,7 +84,7 @@ class BrowserPoolCreateParams(TypedDict, total=False):
timeout_seconds: int
"""
Default idle timeout in seconds for browsers acquired from this pool before they
are destroyed. Defaults to 600 seconds if not specified
are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).
"""

viewport: BrowserViewport
Expand Down
8 changes: 6 additions & 2 deletions src/kernel/types/browser_pool_update_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ class BrowserPoolUpdateParams(TypedDict, total=False):
"""

fill_rate_per_minute: int
"""Percentage of the pool to fill per minute. Defaults to 10%."""
"""Percentage of the pool to fill per minute.

Defaults to 10. The cap is 25 for most organizations but can be raised
per-organization, so only the lower bound is enforced here.
"""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update still allows save_changes

Medium Severity

Release 0.70.0 documents that save_changes is rejected on browser pool update, but BrowserPoolUpdateParams still types profile as BrowserProfile with save_changes, and browser_pools.update forwards that field unchanged. Callers following the SDK can send a field the API rejects.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 77d5b56. Configure here.


headless: bool
"""If true, launches the browser using a headless image. Defaults to false."""
Expand Down Expand Up @@ -86,7 +90,7 @@ class BrowserPoolUpdateParams(TypedDict, total=False):
timeout_seconds: int
"""
Default idle timeout in seconds for browsers acquired from this pool before they
are destroyed. Defaults to 600 seconds if not specified
are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).
"""

viewport: BrowserViewport
Expand Down
7 changes: 4 additions & 3 deletions src/kernel/types/shared/browser_viewport.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ class BrowserViewport(BaseModel):
"""

height: int
"""Browser window height in pixels."""
"""Browser window height in pixels. Any positive integer is accepted."""

width: int
"""Browser window width in pixels."""
"""Browser window width in pixels. Any positive integer is accepted."""

refresh_rate: Optional[int] = None
"""Display refresh rate in Hz.

If omitted, automatically determined from width and height.
Any positive integer is accepted; if omitted, automatically determined from
width and height.
"""
7 changes: 4 additions & 3 deletions src/kernel/types/shared_params/browser_viewport.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ class BrowserViewport(TypedDict, total=False):
"""

height: Required[int]
"""Browser window height in pixels."""
"""Browser window height in pixels. Any positive integer is accepted."""

width: Required[int]
"""Browser window width in pixels."""
"""Browser window width in pixels. Any positive integer is accepted."""

refresh_rate: int
"""Display refresh rate in Hz.

If omitted, automatically determined from width and height.
Any positive integer is accepted; if omitted, automatically determined from
width and height.
"""
8 changes: 4 additions & 4 deletions tests/api_resources/test_browser_pools.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def test_method_create_with_all_params(self, client: Kernel) -> None:
proxy_id="proxy_id",
start_url="https://example.com",
stealth=True,
timeout_seconds=60,
timeout_seconds=10,
viewport={
"height": 800,
"width": 1280,
Expand Down Expand Up @@ -164,7 +164,7 @@ def test_method_update_with_all_params(self, client: Kernel) -> None:
size=10,
start_url="https://example.com",
stealth=True,
timeout_seconds=60,
timeout_seconds=10,
viewport={
"height": 800,
"width": 1280,
Expand Down Expand Up @@ -488,7 +488,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) ->
proxy_id="proxy_id",
start_url="https://example.com",
stealth=True,
timeout_seconds=60,
timeout_seconds=10,
viewport={
"height": 800,
"width": 1280,
Expand Down Expand Up @@ -599,7 +599,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) ->
size=10,
start_url="https://example.com",
stealth=True,
timeout_seconds=60,
timeout_seconds=10,
viewport={
"height": 800,
"width": 1280,
Expand Down
Loading