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
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.133.0"
".": "0.134.0"
}
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
configured_endpoints: 175
configured_endpoints: 176
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## [0.134.0](https://github.com/kernel/kernel-python-sdk/compare/v0.133.0...v0.134.0) (2026-10-28)


### Features

* Add mid-session browser profile saves ([1d70eff](https://github.com/kernel/kernel-python-sdk/commit/1d70eff68d1cc63934aa074e8fd89503845865d6))

## [0.133.0](https://github.com/kernel/kernel-python-sdk/compare/v0.132.0...v0.133.0) (2026-10-28)


Expand Down
2 changes: 2 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ from kernel.types import (
BrowserUsage,
BrowserVideoMemory,
Profile,
SaveProfileRequest,
Tags,
VaultReference,
BrowserCreateResponse,
Expand All @@ -158,6 +159,7 @@ Methods:
- <code title="delete /browsers/{id_or_name}">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">delete_by_id</a>(id_or_name) -> None</code>
- <code title="post /browsers/{id_or_name}/extensions">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">load_extensions</a>(id_or_name, \*\*<a href="src/kernel/types/browser_load_extensions_params.py">params</a>) -> None</code>
- <code title="post /browsers/{id_or_name}/repl">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">repl</a>(id_or_name, \*\*<a href="src/kernel/types/browser_repl_params.py">params</a>) -> <a href="./src/kernel/types/browser_repl_result.py">BrowserReplResult</a></code>
- <code title="post /browsers/{id_or_name}/profiles">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">save_profile</a>(id_or_name, \*\*<a href="src/kernel/types/browser_save_profile_params.py">params</a>) -> <a href="./src/kernel/types/profile.py">Profile</a></code>

## Telemetry

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.133.0"
version = "0.134.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.133.0" # x-release-please-version
__version__ = "0.134.0" # x-release-please-version
174 changes: 174 additions & 0 deletions src/kernel/resources/browsers/browsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
browser_create_params,
browser_update_params,
browser_retrieve_params,
browser_save_profile_params,
browser_load_extensions_params,
)
from .process import (
Expand Down Expand Up @@ -88,6 +89,7 @@
AsyncWebmcpResourceWithStreamingResponse,
)
from ..._base_client import AsyncPaginator, make_request_options
from ...types.profile import Profile
from ...types.tags_param import TagsParam
from .playwright.playwright import (
PlaywrightResource,
Expand Down Expand Up @@ -897,6 +899,86 @@ def repl(
cast_to=BrowserReplResult,
)

def save_profile(
self,
id_or_name: str,
*,
id: str | Omit = omit,
name: 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,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> Profile:
"""
Saves the running browser's current user-data state to an existing or new
profile without ending the browser session.

Saving restarts the browser. Active CDP and WebDriver connections are closed and
must reconnect, and WebDriver clients must create a new session. Open tabs are
restored, but pages reload and in-memory page state is lost. The browser is
stopped only while its user data is copied; this request returns once the
restarted browser accepts CDP connections again and the profile has been
uploaded. Caches, Service Worker storage and Google Drive IndexedDB data are
left out of the saved profile but kept in the running browser.

This does not attach the destination profile to the browser or change its
save_changes setting. Active browsers that already loaded the destination
profile keep their in-memory state. Pools with refresh_on_profile_update enabled
flush idle sessions and replenish them from the new snapshot; other browsers
receive it the next time they load the profile. When saves made with this
endpoint to the same profile overlap, the save that started most recently wins,
even if an earlier one finishes later. The automatic save at the end of a
session whose profile has save_changes enabled is ordered against these saves by
when each finishes.

A successful save restarts the browser's inactivity timeout (timeout_seconds). A
failed save leaves it unchanged.

Returns 409 when the browser is no longer active, when a pooled browser was
released or reacquired after the request was made (browser_lease_changed), or
when the browser is briefly unable to accept a save (browser_busy), in which
case the request can be retried.

Args:
id: Existing profile ID to overwrite.

name: Profile name to overwrite or create.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request

extra_body: Add additional JSON properties to the request

timeout: Override the client-level default timeout for this request, in seconds

idempotency_key: Specify a custom idempotency key for this request
"""
if not id_or_name:
raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
return self._post(
path_template("/browsers/{id_or_name}/profiles", id_or_name=id_or_name),
body=maybe_transform(
{
"id": id,
"name": name,
},
browser_save_profile_params.BrowserSaveProfileParams,
),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
idempotency_key=idempotency_key,
),
cast_to=Profile,
)


class AsyncBrowsersResource(AsyncAPIResource):
@cached_property
Expand Down Expand Up @@ -1671,6 +1753,86 @@ async def repl(
cast_to=BrowserReplResult,
)

async def save_profile(
self,
id_or_name: str,
*,
id: str | Omit = omit,
name: 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,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> Profile:
"""
Saves the running browser's current user-data state to an existing or new
profile without ending the browser session.

Saving restarts the browser. Active CDP and WebDriver connections are closed and
must reconnect, and WebDriver clients must create a new session. Open tabs are
restored, but pages reload and in-memory page state is lost. The browser is
stopped only while its user data is copied; this request returns once the
restarted browser accepts CDP connections again and the profile has been
uploaded. Caches, Service Worker storage and Google Drive IndexedDB data are
left out of the saved profile but kept in the running browser.

This does not attach the destination profile to the browser or change its
save_changes setting. Active browsers that already loaded the destination
profile keep their in-memory state. Pools with refresh_on_profile_update enabled
flush idle sessions and replenish them from the new snapshot; other browsers
receive it the next time they load the profile. When saves made with this
endpoint to the same profile overlap, the save that started most recently wins,
even if an earlier one finishes later. The automatic save at the end of a
session whose profile has save_changes enabled is ordered against these saves by
when each finishes.

A successful save restarts the browser's inactivity timeout (timeout_seconds). A
failed save leaves it unchanged.

Returns 409 when the browser is no longer active, when a pooled browser was
released or reacquired after the request was made (browser_lease_changed), or
when the browser is briefly unable to accept a save (browser_busy), in which
case the request can be retried.

Args:
id: Existing profile ID to overwrite.

name: Profile name to overwrite or create.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request

extra_body: Add additional JSON properties to the request

timeout: Override the client-level default timeout for this request, in seconds

idempotency_key: Specify a custom idempotency key for this request
"""
if not id_or_name:
raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
return await self._post(
path_template("/browsers/{id_or_name}/profiles", id_or_name=id_or_name),
body=await async_maybe_transform(
{
"id": id,
"name": name,
},
browser_save_profile_params.BrowserSaveProfileParams,
),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
idempotency_key=idempotency_key,
),
cast_to=Profile,
)


class BrowsersResourceWithRawResponse:
def __init__(self, browsers: BrowsersResource) -> None:
Expand Down Expand Up @@ -1700,6 +1862,9 @@ def __init__(self, browsers: BrowsersResource) -> None:
self.repl = to_raw_response_wrapper(
browsers.repl,
)
self.save_profile = to_raw_response_wrapper(
browsers.save_profile,
)

@cached_property
def telemetry(self) -> TelemetryResourceWithRawResponse:
Expand Down Expand Up @@ -1774,6 +1939,9 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None:
self.repl = async_to_raw_response_wrapper(
browsers.repl,
)
self.save_profile = async_to_raw_response_wrapper(
browsers.save_profile,
)

@cached_property
def telemetry(self) -> AsyncTelemetryResourceWithRawResponse:
Expand Down Expand Up @@ -1848,6 +2016,9 @@ def __init__(self, browsers: BrowsersResource) -> None:
self.repl = to_streamed_response_wrapper(
browsers.repl,
)
self.save_profile = to_streamed_response_wrapper(
browsers.save_profile,
)

@cached_property
def telemetry(self) -> TelemetryResourceWithStreamingResponse:
Expand Down Expand Up @@ -1922,6 +2093,9 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None:
self.repl = async_to_streamed_response_wrapper(
browsers.repl,
)
self.save_profile = async_to_streamed_response_wrapper(
browsers.save_profile,
)

@cached_property
def telemetry(self) -> AsyncTelemetryResourceWithStreamingResponse:
Expand Down
1 change: 1 addition & 0 deletions src/kernel/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
from .invocation_update_response import InvocationUpdateResponse as InvocationUpdateResponse
from .browser_pool_acquire_params import BrowserPoolAcquireParams as BrowserPoolAcquireParams
from .browser_pool_release_params import BrowserPoolReleaseParams as BrowserPoolReleaseParams
from .browser_save_profile_params import BrowserSaveProfileParams as BrowserSaveProfileParams
from .config_registry_list_params import ConfigRegistryListParams as ConfigRegistryListParams
from .browser_network_config_param import BrowserNetworkConfigParam as BrowserNetworkConfigParam
from .browser_network_update_param import BrowserNetworkUpdateParam as BrowserNetworkUpdateParam
Expand Down
15 changes: 15 additions & 0 deletions src/kernel/types/browser_save_profile_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from __future__ import annotations

from typing_extensions import TypedDict

__all__ = ["BrowserSaveProfileParams"]


class BrowserSaveProfileParams(TypedDict, total=False):
id: str
"""Existing profile ID to overwrite."""

name: str
"""Profile name to overwrite or create."""
Loading
Loading