From 9a1e7bf9c92d64da4a151dd44cc60057c75c63bf Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 22 Nov 2025 03:34:11 +0000
Subject: [PATCH 01/10] chore: add Python 3.14 classifier and testing
---
pyproject.toml | 1 +
1 file changed, 1 insertion(+)
diff --git a/pyproject.toml b/pyproject.toml
index b5d3ecb5..43139568 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,6 +24,7 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
"Operating System :: OS Independent",
"Operating System :: POSIX",
"Operating System :: MacOS",
From b8729284ba804461749dad0ac4613aea3c6b3ce6 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 24 Nov 2025 18:52:40 +0000
Subject: [PATCH 02/10] feat: Mason/agent auth api
---
.stats.yml | 8 +-
api.md | 35 ++
src/kernel/_client.py | 9 +
src/kernel/resources/__init__.py | 14 +
src/kernel/resources/agents/__init__.py | 33 ++
src/kernel/resources/agents/agents.py | 102 ++++
src/kernel/resources/agents/auth/__init__.py | 33 ++
src/kernel/resources/agents/auth/auth.py | 239 ++++++++++
src/kernel/resources/agents/auth/runs.py | 434 ++++++++++++++++++
src/kernel/types/agents/__init__.py | 10 +
.../agents/agent_auth_discover_response.py | 28 ++
.../types/agents/agent_auth_run_response.py | 22 +
.../types/agents/agent_auth_start_response.py | 21 +
.../agents/agent_auth_submit_response.py | 34 ++
src/kernel/types/agents/auth/__init__.py | 7 +
.../types/agents/auth/run_exchange_params.py | 12 +
.../agents/auth/run_exchange_response.py | 13 +
.../types/agents/auth/run_submit_params.py | 13 +
src/kernel/types/agents/auth_start_params.py | 26 ++
src/kernel/types/agents/discovered_field.py | 28 ++
tests/api_resources/agents/__init__.py | 1 +
tests/api_resources/agents/auth/__init__.py | 1 +
tests/api_resources/agents/auth/test_runs.py | 401 ++++++++++++++++
tests/api_resources/agents/test_auth.py | 120 +++++
24 files changed, 1640 insertions(+), 4 deletions(-)
create mode 100644 src/kernel/resources/agents/__init__.py
create mode 100644 src/kernel/resources/agents/agents.py
create mode 100644 src/kernel/resources/agents/auth/__init__.py
create mode 100644 src/kernel/resources/agents/auth/auth.py
create mode 100644 src/kernel/resources/agents/auth/runs.py
create mode 100644 src/kernel/types/agents/__init__.py
create mode 100644 src/kernel/types/agents/agent_auth_discover_response.py
create mode 100644 src/kernel/types/agents/agent_auth_run_response.py
create mode 100644 src/kernel/types/agents/agent_auth_start_response.py
create mode 100644 src/kernel/types/agents/agent_auth_submit_response.py
create mode 100644 src/kernel/types/agents/auth/__init__.py
create mode 100644 src/kernel/types/agents/auth/run_exchange_params.py
create mode 100644 src/kernel/types/agents/auth/run_exchange_response.py
create mode 100644 src/kernel/types/agents/auth/run_submit_params.py
create mode 100644 src/kernel/types/agents/auth_start_params.py
create mode 100644 src/kernel/types/agents/discovered_field.py
create mode 100644 tests/api_resources/agents/__init__.py
create mode 100644 tests/api_resources/agents/auth/__init__.py
create mode 100644 tests/api_resources/agents/auth/test_runs.py
create mode 100644 tests/api_resources/agents/test_auth.py
diff --git a/.stats.yml b/.stats.yml
index 11b820d4..bdbede3e 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 66
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af1b468584cb44aa9babbbfb82bff4055614fbb5c815084a6b7dacc1cf1a822.yml
-openapi_spec_hash: 891affa2849341ea01d62011125f7edc
-config_hash: 9421eb86b7f3f4b274f123279da3858e
+configured_endpoints: 71
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb3f37e55117a56e7a4208bd646d3a68adeb651ced8531e13fbfc1fc9dcb05a4.yml
+openapi_spec_hash: 7303ce8ce3130e16a6a5c2bb49e43e9b
+config_hash: be146470fb2d4583b6533859f0fa48f5
diff --git a/api.md b/api.md
index afa0ddd4..483ff9cb 100644
--- a/api.md
+++ b/api.md
@@ -243,3 +243,38 @@ Methods:
- client.extensions.download(id_or_name) -> BinaryAPIResponse
- client.extensions.download_from_chrome_store(\*\*params) -> BinaryAPIResponse
- client.extensions.upload(\*\*params) -> ExtensionUploadResponse
+
+# Agents
+
+## Auth
+
+Types:
+
+```python
+from kernel.types.agents import (
+ AgentAuthDiscoverResponse,
+ AgentAuthRunResponse,
+ AgentAuthStartResponse,
+ AgentAuthSubmitResponse,
+ DiscoveredField,
+)
+```
+
+Methods:
+
+- client.agents.auth.start(\*\*params) -> AgentAuthStartResponse
+
+### Runs
+
+Types:
+
+```python
+from kernel.types.agents.auth import RunExchangeResponse
+```
+
+Methods:
+
+- client.agents.auth.runs.retrieve(run_id) -> AgentAuthRunResponse
+- client.agents.auth.runs.discover(run_id) -> AgentAuthDiscoverResponse
+- client.agents.auth.runs.exchange(run_id, \*\*params) -> RunExchangeResponse
+- client.agents.auth.runs.submit(run_id, \*\*params) -> AgentAuthSubmitResponse
diff --git a/src/kernel/_client.py b/src/kernel/_client.py
index ea9e51b9..ba424335 100644
--- a/src/kernel/_client.py
+++ b/src/kernel/_client.py
@@ -29,6 +29,7 @@
SyncAPIClient,
AsyncAPIClient,
)
+from .resources.agents import agents
from .resources.browsers import browsers
__all__ = [
@@ -57,6 +58,7 @@ class Kernel(SyncAPIClient):
profiles: profiles.ProfilesResource
proxies: proxies.ProxiesResource
extensions: extensions.ExtensionsResource
+ agents: agents.AgentsResource
with_raw_response: KernelWithRawResponse
with_streaming_response: KernelWithStreamedResponse
@@ -145,6 +147,7 @@ def __init__(
self.profiles = profiles.ProfilesResource(self)
self.proxies = proxies.ProxiesResource(self)
self.extensions = extensions.ExtensionsResource(self)
+ self.agents = agents.AgentsResource(self)
self.with_raw_response = KernelWithRawResponse(self)
self.with_streaming_response = KernelWithStreamedResponse(self)
@@ -263,6 +266,7 @@ class AsyncKernel(AsyncAPIClient):
profiles: profiles.AsyncProfilesResource
proxies: proxies.AsyncProxiesResource
extensions: extensions.AsyncExtensionsResource
+ agents: agents.AsyncAgentsResource
with_raw_response: AsyncKernelWithRawResponse
with_streaming_response: AsyncKernelWithStreamedResponse
@@ -351,6 +355,7 @@ def __init__(
self.profiles = profiles.AsyncProfilesResource(self)
self.proxies = proxies.AsyncProxiesResource(self)
self.extensions = extensions.AsyncExtensionsResource(self)
+ self.agents = agents.AsyncAgentsResource(self)
self.with_raw_response = AsyncKernelWithRawResponse(self)
self.with_streaming_response = AsyncKernelWithStreamedResponse(self)
@@ -470,6 +475,7 @@ def __init__(self, client: Kernel) -> None:
self.profiles = profiles.ProfilesResourceWithRawResponse(client.profiles)
self.proxies = proxies.ProxiesResourceWithRawResponse(client.proxies)
self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions)
+ self.agents = agents.AgentsResourceWithRawResponse(client.agents)
class AsyncKernelWithRawResponse:
@@ -481,6 +487,7 @@ def __init__(self, client: AsyncKernel) -> None:
self.profiles = profiles.AsyncProfilesResourceWithRawResponse(client.profiles)
self.proxies = proxies.AsyncProxiesResourceWithRawResponse(client.proxies)
self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions)
+ self.agents = agents.AsyncAgentsResourceWithRawResponse(client.agents)
class KernelWithStreamedResponse:
@@ -492,6 +499,7 @@ def __init__(self, client: Kernel) -> None:
self.profiles = profiles.ProfilesResourceWithStreamingResponse(client.profiles)
self.proxies = proxies.ProxiesResourceWithStreamingResponse(client.proxies)
self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions)
+ self.agents = agents.AgentsResourceWithStreamingResponse(client.agents)
class AsyncKernelWithStreamedResponse:
@@ -503,6 +511,7 @@ def __init__(self, client: AsyncKernel) -> None:
self.profiles = profiles.AsyncProfilesResourceWithStreamingResponse(client.profiles)
self.proxies = proxies.AsyncProxiesResourceWithStreamingResponse(client.proxies)
self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions)
+ self.agents = agents.AsyncAgentsResourceWithStreamingResponse(client.agents)
Client = Kernel
diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py
index 1b68d89f..233ef508 100644
--- a/src/kernel/resources/__init__.py
+++ b/src/kernel/resources/__init__.py
@@ -8,6 +8,14 @@
AppsResourceWithStreamingResponse,
AsyncAppsResourceWithStreamingResponse,
)
+from .agents import (
+ AgentsResource,
+ AsyncAgentsResource,
+ AgentsResourceWithRawResponse,
+ AsyncAgentsResourceWithRawResponse,
+ AgentsResourceWithStreamingResponse,
+ AsyncAgentsResourceWithStreamingResponse,
+)
from .proxies import (
ProxiesResource,
AsyncProxiesResource,
@@ -100,4 +108,10 @@
"AsyncExtensionsResourceWithRawResponse",
"ExtensionsResourceWithStreamingResponse",
"AsyncExtensionsResourceWithStreamingResponse",
+ "AgentsResource",
+ "AsyncAgentsResource",
+ "AgentsResourceWithRawResponse",
+ "AsyncAgentsResourceWithRawResponse",
+ "AgentsResourceWithStreamingResponse",
+ "AsyncAgentsResourceWithStreamingResponse",
]
diff --git a/src/kernel/resources/agents/__init__.py b/src/kernel/resources/agents/__init__.py
new file mode 100644
index 00000000..cb159eb7
--- /dev/null
+++ b/src/kernel/resources/agents/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .auth import (
+ AuthResource,
+ AsyncAuthResource,
+ AuthResourceWithRawResponse,
+ AsyncAuthResourceWithRawResponse,
+ AuthResourceWithStreamingResponse,
+ AsyncAuthResourceWithStreamingResponse,
+)
+from .agents import (
+ AgentsResource,
+ AsyncAgentsResource,
+ AgentsResourceWithRawResponse,
+ AsyncAgentsResourceWithRawResponse,
+ AgentsResourceWithStreamingResponse,
+ AsyncAgentsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "AuthResource",
+ "AsyncAuthResource",
+ "AuthResourceWithRawResponse",
+ "AsyncAuthResourceWithRawResponse",
+ "AuthResourceWithStreamingResponse",
+ "AsyncAuthResourceWithStreamingResponse",
+ "AgentsResource",
+ "AsyncAgentsResource",
+ "AgentsResourceWithRawResponse",
+ "AsyncAgentsResourceWithRawResponse",
+ "AgentsResourceWithStreamingResponse",
+ "AsyncAgentsResourceWithStreamingResponse",
+]
diff --git a/src/kernel/resources/agents/agents.py b/src/kernel/resources/agents/agents.py
new file mode 100644
index 00000000..b7bb580c
--- /dev/null
+++ b/src/kernel/resources/agents/agents.py
@@ -0,0 +1,102 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from ..._compat import cached_property
+from .auth.auth import (
+ AuthResource,
+ AsyncAuthResource,
+ AuthResourceWithRawResponse,
+ AsyncAuthResourceWithRawResponse,
+ AuthResourceWithStreamingResponse,
+ AsyncAuthResourceWithStreamingResponse,
+)
+from ..._resource import SyncAPIResource, AsyncAPIResource
+
+__all__ = ["AgentsResource", "AsyncAgentsResource"]
+
+
+class AgentsResource(SyncAPIResource):
+ @cached_property
+ def auth(self) -> AuthResource:
+ return AuthResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AgentsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AgentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AgentsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return AgentsResourceWithStreamingResponse(self)
+
+
+class AsyncAgentsResource(AsyncAPIResource):
+ @cached_property
+ def auth(self) -> AsyncAuthResource:
+ return AsyncAuthResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncAgentsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AsyncAgentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAgentsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return AsyncAgentsResourceWithStreamingResponse(self)
+
+
+class AgentsResourceWithRawResponse:
+ def __init__(self, agents: AgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def auth(self) -> AuthResourceWithRawResponse:
+ return AuthResourceWithRawResponse(self._agents.auth)
+
+
+class AsyncAgentsResourceWithRawResponse:
+ def __init__(self, agents: AsyncAgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def auth(self) -> AsyncAuthResourceWithRawResponse:
+ return AsyncAuthResourceWithRawResponse(self._agents.auth)
+
+
+class AgentsResourceWithStreamingResponse:
+ def __init__(self, agents: AgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def auth(self) -> AuthResourceWithStreamingResponse:
+ return AuthResourceWithStreamingResponse(self._agents.auth)
+
+
+class AsyncAgentsResourceWithStreamingResponse:
+ def __init__(self, agents: AsyncAgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def auth(self) -> AsyncAuthResourceWithStreamingResponse:
+ return AsyncAuthResourceWithStreamingResponse(self._agents.auth)
diff --git a/src/kernel/resources/agents/auth/__init__.py b/src/kernel/resources/agents/auth/__init__.py
new file mode 100644
index 00000000..d9853204
--- /dev/null
+++ b/src/kernel/resources/agents/auth/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .auth import (
+ AuthResource,
+ AsyncAuthResource,
+ AuthResourceWithRawResponse,
+ AsyncAuthResourceWithRawResponse,
+ AuthResourceWithStreamingResponse,
+ AsyncAuthResourceWithStreamingResponse,
+)
+from .runs import (
+ RunsResource,
+ AsyncRunsResource,
+ RunsResourceWithRawResponse,
+ AsyncRunsResourceWithRawResponse,
+ RunsResourceWithStreamingResponse,
+ AsyncRunsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "RunsResource",
+ "AsyncRunsResource",
+ "RunsResourceWithRawResponse",
+ "AsyncRunsResourceWithRawResponse",
+ "RunsResourceWithStreamingResponse",
+ "AsyncRunsResourceWithStreamingResponse",
+ "AuthResource",
+ "AsyncAuthResource",
+ "AuthResourceWithRawResponse",
+ "AsyncAuthResourceWithRawResponse",
+ "AuthResourceWithStreamingResponse",
+ "AsyncAuthResourceWithStreamingResponse",
+]
diff --git a/src/kernel/resources/agents/auth/auth.py b/src/kernel/resources/agents/auth/auth.py
new file mode 100644
index 00000000..2e099095
--- /dev/null
+++ b/src/kernel/resources/agents/auth/auth.py
@@ -0,0 +1,239 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from .runs import (
+ RunsResource,
+ AsyncRunsResource,
+ RunsResourceWithRawResponse,
+ AsyncRunsResourceWithRawResponse,
+ RunsResourceWithStreamingResponse,
+ AsyncRunsResourceWithStreamingResponse,
+)
+from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ...._utils import maybe_transform, async_maybe_transform
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...._base_client import make_request_options
+from ....types.agents import auth_start_params
+from ....types.agents.agent_auth_start_response import AgentAuthStartResponse
+
+__all__ = ["AuthResource", "AsyncAuthResource"]
+
+
+class AuthResource(SyncAPIResource):
+ @cached_property
+ def runs(self) -> RunsResource:
+ return RunsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AuthResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AuthResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AuthResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return AuthResourceWithStreamingResponse(self)
+
+ def start(
+ self,
+ *,
+ profile_name: str,
+ target_domain: str,
+ app_logo_url: str | Omit = omit,
+ proxy: auth_start_params.Proxy | 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,
+ ) -> AgentAuthStartResponse:
+ """Creates a browser session and returns a handoff code for the hosted flow.
+
+ Uses
+ standard API key or JWT authentication (not the JWT returned by the exchange
+ endpoint).
+
+ Args:
+ profile_name: Name of the profile to use for this flow
+
+ target_domain: Target domain for authentication
+
+ app_logo_url: Optional logo URL for the application
+
+ proxy: Optional proxy configuration
+
+ 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
+ """
+ return self._post(
+ "/agents/auth/start",
+ body=maybe_transform(
+ {
+ "profile_name": profile_name,
+ "target_domain": target_domain,
+ "app_logo_url": app_logo_url,
+ "proxy": proxy,
+ },
+ auth_start_params.AuthStartParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthStartResponse,
+ )
+
+
+class AsyncAuthResource(AsyncAPIResource):
+ @cached_property
+ def runs(self) -> AsyncRunsResource:
+ return AsyncRunsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncAuthResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AsyncAuthResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAuthResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return AsyncAuthResourceWithStreamingResponse(self)
+
+ async def start(
+ self,
+ *,
+ profile_name: str,
+ target_domain: str,
+ app_logo_url: str | Omit = omit,
+ proxy: auth_start_params.Proxy | 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,
+ ) -> AgentAuthStartResponse:
+ """Creates a browser session and returns a handoff code for the hosted flow.
+
+ Uses
+ standard API key or JWT authentication (not the JWT returned by the exchange
+ endpoint).
+
+ Args:
+ profile_name: Name of the profile to use for this flow
+
+ target_domain: Target domain for authentication
+
+ app_logo_url: Optional logo URL for the application
+
+ proxy: Optional proxy configuration
+
+ 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
+ """
+ return await self._post(
+ "/agents/auth/start",
+ body=await async_maybe_transform(
+ {
+ "profile_name": profile_name,
+ "target_domain": target_domain,
+ "app_logo_url": app_logo_url,
+ "proxy": proxy,
+ },
+ auth_start_params.AuthStartParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthStartResponse,
+ )
+
+
+class AuthResourceWithRawResponse:
+ def __init__(self, auth: AuthResource) -> None:
+ self._auth = auth
+
+ self.start = to_raw_response_wrapper(
+ auth.start,
+ )
+
+ @cached_property
+ def runs(self) -> RunsResourceWithRawResponse:
+ return RunsResourceWithRawResponse(self._auth.runs)
+
+
+class AsyncAuthResourceWithRawResponse:
+ def __init__(self, auth: AsyncAuthResource) -> None:
+ self._auth = auth
+
+ self.start = async_to_raw_response_wrapper(
+ auth.start,
+ )
+
+ @cached_property
+ def runs(self) -> AsyncRunsResourceWithRawResponse:
+ return AsyncRunsResourceWithRawResponse(self._auth.runs)
+
+
+class AuthResourceWithStreamingResponse:
+ def __init__(self, auth: AuthResource) -> None:
+ self._auth = auth
+
+ self.start = to_streamed_response_wrapper(
+ auth.start,
+ )
+
+ @cached_property
+ def runs(self) -> RunsResourceWithStreamingResponse:
+ return RunsResourceWithStreamingResponse(self._auth.runs)
+
+
+class AsyncAuthResourceWithStreamingResponse:
+ def __init__(self, auth: AsyncAuthResource) -> None:
+ self._auth = auth
+
+ self.start = async_to_streamed_response_wrapper(
+ auth.start,
+ )
+
+ @cached_property
+ def runs(self) -> AsyncRunsResourceWithStreamingResponse:
+ return AsyncRunsResourceWithStreamingResponse(self._auth.runs)
diff --git a/src/kernel/resources/agents/auth/runs.py b/src/kernel/resources/agents/auth/runs.py
new file mode 100644
index 00000000..6ea09403
--- /dev/null
+++ b/src/kernel/resources/agents/auth/runs.py
@@ -0,0 +1,434 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+
+import httpx
+
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import maybe_transform, async_maybe_transform
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...._base_client import make_request_options
+from ....types.agents.auth import run_submit_params, run_exchange_params
+from ....types.agents.agent_auth_run_response import AgentAuthRunResponse
+from ....types.agents.agent_auth_submit_response import AgentAuthSubmitResponse
+from ....types.agents.auth.run_exchange_response import RunExchangeResponse
+from ....types.agents.agent_auth_discover_response import AgentAuthDiscoverResponse
+
+__all__ = ["RunsResource", "AsyncRunsResource"]
+
+
+class RunsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> RunsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return RunsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> RunsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return RunsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ run_id: str,
+ *,
+ # 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,
+ ) -> AgentAuthRunResponse:
+ """Returns run details including app_name and target_domain.
+
+ Uses the JWT returned
+ by the exchange endpoint, or standard API key or JWT authentication.
+
+ Args:
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return self._get(
+ f"/agents/auth/runs/{run_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthRunResponse,
+ )
+
+ def discover(
+ self,
+ run_id: str,
+ *,
+ # 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,
+ ) -> AgentAuthDiscoverResponse:
+ """
+ Inspects the target site to detect logged-in state or discover required fields.
+ Returns 200 with success: true when fields are found, or 4xx/5xx for failures.
+ Requires the JWT returned by the exchange endpoint.
+
+ Args:
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return self._post(
+ f"/agents/auth/runs/{run_id}/discover",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthDiscoverResponse,
+ )
+
+ def exchange(
+ self,
+ run_id: str,
+ *,
+ code: str,
+ # 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,
+ ) -> RunExchangeResponse:
+ """Validates the handoff code and returns a JWT token for subsequent requests.
+
+ No
+ authentication required (the handoff code serves as the credential).
+
+ Args:
+ code: Handoff code from start endpoint
+
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return self._post(
+ f"/agents/auth/runs/{run_id}/exchange",
+ body=maybe_transform({"code": code}, run_exchange_params.RunExchangeParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=RunExchangeResponse,
+ )
+
+ def submit(
+ self,
+ run_id: str,
+ *,
+ field_values: Dict[str, str],
+ # 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,
+ ) -> AgentAuthSubmitResponse:
+ """
+ Submits field values for the discovered login form and may return additional
+ auth fields or success. Requires the JWT returned by the exchange endpoint.
+
+ Args:
+ field_values: Values for the discovered login fields
+
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return self._post(
+ f"/agents/auth/runs/{run_id}/submit",
+ body=maybe_transform({"field_values": field_values}, run_submit_params.RunSubmitParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthSubmitResponse,
+ )
+
+
+class AsyncRunsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncRunsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AsyncRunsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncRunsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return AsyncRunsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ run_id: str,
+ *,
+ # 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,
+ ) -> AgentAuthRunResponse:
+ """Returns run details including app_name and target_domain.
+
+ Uses the JWT returned
+ by the exchange endpoint, or standard API key or JWT authentication.
+
+ Args:
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return await self._get(
+ f"/agents/auth/runs/{run_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthRunResponse,
+ )
+
+ async def discover(
+ self,
+ run_id: str,
+ *,
+ # 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,
+ ) -> AgentAuthDiscoverResponse:
+ """
+ Inspects the target site to detect logged-in state or discover required fields.
+ Returns 200 with success: true when fields are found, or 4xx/5xx for failures.
+ Requires the JWT returned by the exchange endpoint.
+
+ Args:
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return await self._post(
+ f"/agents/auth/runs/{run_id}/discover",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthDiscoverResponse,
+ )
+
+ async def exchange(
+ self,
+ run_id: str,
+ *,
+ code: str,
+ # 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,
+ ) -> RunExchangeResponse:
+ """Validates the handoff code and returns a JWT token for subsequent requests.
+
+ No
+ authentication required (the handoff code serves as the credential).
+
+ Args:
+ code: Handoff code from start endpoint
+
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return await self._post(
+ f"/agents/auth/runs/{run_id}/exchange",
+ body=await async_maybe_transform({"code": code}, run_exchange_params.RunExchangeParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=RunExchangeResponse,
+ )
+
+ async def submit(
+ self,
+ run_id: str,
+ *,
+ field_values: Dict[str, str],
+ # 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,
+ ) -> AgentAuthSubmitResponse:
+ """
+ Submits field values for the discovered login form and may return additional
+ auth fields or success. Requires the JWT returned by the exchange endpoint.
+
+ Args:
+ field_values: Values for the discovered login fields
+
+ 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
+ """
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return await self._post(
+ f"/agents/auth/runs/{run_id}/submit",
+ body=await async_maybe_transform({"field_values": field_values}, run_submit_params.RunSubmitParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentAuthSubmitResponse,
+ )
+
+
+class RunsResourceWithRawResponse:
+ def __init__(self, runs: RunsResource) -> None:
+ self._runs = runs
+
+ self.retrieve = to_raw_response_wrapper(
+ runs.retrieve,
+ )
+ self.discover = to_raw_response_wrapper(
+ runs.discover,
+ )
+ self.exchange = to_raw_response_wrapper(
+ runs.exchange,
+ )
+ self.submit = to_raw_response_wrapper(
+ runs.submit,
+ )
+
+
+class AsyncRunsResourceWithRawResponse:
+ def __init__(self, runs: AsyncRunsResource) -> None:
+ self._runs = runs
+
+ self.retrieve = async_to_raw_response_wrapper(
+ runs.retrieve,
+ )
+ self.discover = async_to_raw_response_wrapper(
+ runs.discover,
+ )
+ self.exchange = async_to_raw_response_wrapper(
+ runs.exchange,
+ )
+ self.submit = async_to_raw_response_wrapper(
+ runs.submit,
+ )
+
+
+class RunsResourceWithStreamingResponse:
+ def __init__(self, runs: RunsResource) -> None:
+ self._runs = runs
+
+ self.retrieve = to_streamed_response_wrapper(
+ runs.retrieve,
+ )
+ self.discover = to_streamed_response_wrapper(
+ runs.discover,
+ )
+ self.exchange = to_streamed_response_wrapper(
+ runs.exchange,
+ )
+ self.submit = to_streamed_response_wrapper(
+ runs.submit,
+ )
+
+
+class AsyncRunsResourceWithStreamingResponse:
+ def __init__(self, runs: AsyncRunsResource) -> None:
+ self._runs = runs
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ runs.retrieve,
+ )
+ self.discover = async_to_streamed_response_wrapper(
+ runs.discover,
+ )
+ self.exchange = async_to_streamed_response_wrapper(
+ runs.exchange,
+ )
+ self.submit = async_to_streamed_response_wrapper(
+ runs.submit,
+ )
diff --git a/src/kernel/types/agents/__init__.py b/src/kernel/types/agents/__init__.py
new file mode 100644
index 00000000..e8c22774
--- /dev/null
+++ b/src/kernel/types/agents/__init__.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .discovered_field import DiscoveredField as DiscoveredField
+from .auth_start_params import AuthStartParams as AuthStartParams
+from .agent_auth_run_response import AgentAuthRunResponse as AgentAuthRunResponse
+from .agent_auth_start_response import AgentAuthStartResponse as AgentAuthStartResponse
+from .agent_auth_submit_response import AgentAuthSubmitResponse as AgentAuthSubmitResponse
+from .agent_auth_discover_response import AgentAuthDiscoverResponse as AgentAuthDiscoverResponse
diff --git a/src/kernel/types/agents/agent_auth_discover_response.py b/src/kernel/types/agents/agent_auth_discover_response.py
new file mode 100644
index 00000000..000bdec2
--- /dev/null
+++ b/src/kernel/types/agents/agent_auth_discover_response.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+from .discovered_field import DiscoveredField
+
+__all__ = ["AgentAuthDiscoverResponse"]
+
+
+class AgentAuthDiscoverResponse(BaseModel):
+ success: bool
+ """Whether discovery succeeded"""
+
+ error_message: Optional[str] = None
+ """Error message if discovery failed"""
+
+ fields: Optional[List[DiscoveredField]] = None
+ """Discovered form fields (present when success is true)"""
+
+ logged_in: Optional[bool] = None
+ """Whether user is already logged in"""
+
+ login_url: Optional[str] = None
+ """URL of the discovered login page"""
+
+ page_title: Optional[str] = None
+ """Title of the login page"""
diff --git a/src/kernel/types/agents/agent_auth_run_response.py b/src/kernel/types/agents/agent_auth_run_response.py
new file mode 100644
index 00000000..0ec0b0bb
--- /dev/null
+++ b/src/kernel/types/agents/agent_auth_run_response.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["AgentAuthRunResponse"]
+
+
+class AgentAuthRunResponse(BaseModel):
+ app_name: str
+ """App name (org name at time of run creation)"""
+
+ expires_at: datetime
+ """When the handoff code expires"""
+
+ status: Literal["ACTIVE", "ENDED", "EXPIRED", "CANCELED"]
+ """Run status"""
+
+ target_domain: str
+ """Target domain for authentication"""
diff --git a/src/kernel/types/agents/agent_auth_start_response.py b/src/kernel/types/agents/agent_auth_start_response.py
new file mode 100644
index 00000000..2855fc2d
--- /dev/null
+++ b/src/kernel/types/agents/agent_auth_start_response.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+
+from ..._models import BaseModel
+
+__all__ = ["AgentAuthStartResponse"]
+
+
+class AgentAuthStartResponse(BaseModel):
+ expires_at: datetime
+ """When the handoff code expires"""
+
+ handoff_code: str
+ """One-time code for handoff"""
+
+ hosted_url: str
+ """URL to redirect user to"""
+
+ run_id: str
+ """Unique identifier for the run"""
diff --git a/src/kernel/types/agents/agent_auth_submit_response.py b/src/kernel/types/agents/agent_auth_submit_response.py
new file mode 100644
index 00000000..c57002fb
--- /dev/null
+++ b/src/kernel/types/agents/agent_auth_submit_response.py
@@ -0,0 +1,34 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+from .discovered_field import DiscoveredField
+
+__all__ = ["AgentAuthSubmitResponse"]
+
+
+class AgentAuthSubmitResponse(BaseModel):
+ success: bool
+ """Whether submission succeeded"""
+
+ additional_fields: Optional[List[DiscoveredField]] = None
+ """
+ Additional fields needed (e.g., OTP) - present when needs_additional_auth is
+ true
+ """
+
+ app_name: Optional[str] = None
+ """App name (only present when logged_in is true)"""
+
+ error_message: Optional[str] = None
+ """Error message if submission failed"""
+
+ logged_in: Optional[bool] = None
+ """Whether user is now logged in"""
+
+ needs_additional_auth: Optional[bool] = None
+ """Whether additional authentication fields are needed"""
+
+ target_domain: Optional[str] = None
+ """Target domain (only present when logged_in is true)"""
diff --git a/src/kernel/types/agents/auth/__init__.py b/src/kernel/types/agents/auth/__init__.py
new file mode 100644
index 00000000..78a13a38
--- /dev/null
+++ b/src/kernel/types/agents/auth/__init__.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .run_submit_params import RunSubmitParams as RunSubmitParams
+from .run_exchange_params import RunExchangeParams as RunExchangeParams
+from .run_exchange_response import RunExchangeResponse as RunExchangeResponse
diff --git a/src/kernel/types/agents/auth/run_exchange_params.py b/src/kernel/types/agents/auth/run_exchange_params.py
new file mode 100644
index 00000000..1a23b25d
--- /dev/null
+++ b/src/kernel/types/agents/auth/run_exchange_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["RunExchangeParams"]
+
+
+class RunExchangeParams(TypedDict, total=False):
+ code: Required[str]
+ """Handoff code from start endpoint"""
diff --git a/src/kernel/types/agents/auth/run_exchange_response.py b/src/kernel/types/agents/auth/run_exchange_response.py
new file mode 100644
index 00000000..347c57c3
--- /dev/null
+++ b/src/kernel/types/agents/auth/run_exchange_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ...._models import BaseModel
+
+__all__ = ["RunExchangeResponse"]
+
+
+class RunExchangeResponse(BaseModel):
+ jwt: str
+ """JWT token with run_id claim (30 minute TTL)"""
+
+ run_id: str
+ """Run ID"""
diff --git a/src/kernel/types/agents/auth/run_submit_params.py b/src/kernel/types/agents/auth/run_submit_params.py
new file mode 100644
index 00000000..efaf9ea5
--- /dev/null
+++ b/src/kernel/types/agents/auth/run_submit_params.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import Required, TypedDict
+
+__all__ = ["RunSubmitParams"]
+
+
+class RunSubmitParams(TypedDict, total=False):
+ field_values: Required[Dict[str, str]]
+ """Values for the discovered login fields"""
diff --git a/src/kernel/types/agents/auth_start_params.py b/src/kernel/types/agents/auth_start_params.py
new file mode 100644
index 00000000..6e0f0c82
--- /dev/null
+++ b/src/kernel/types/agents/auth_start_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["AuthStartParams", "Proxy"]
+
+
+class AuthStartParams(TypedDict, total=False):
+ profile_name: Required[str]
+ """Name of the profile to use for this flow"""
+
+ target_domain: Required[str]
+ """Target domain for authentication"""
+
+ app_logo_url: str
+ """Optional logo URL for the application"""
+
+ proxy: Proxy
+ """Optional proxy configuration"""
+
+
+class Proxy(TypedDict, total=False):
+ proxy_id: str
+ """ID of the proxy to use"""
diff --git a/src/kernel/types/agents/discovered_field.py b/src/kernel/types/agents/discovered_field.py
new file mode 100644
index 00000000..90a4864c
--- /dev/null
+++ b/src/kernel/types/agents/discovered_field.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["DiscoveredField"]
+
+
+class DiscoveredField(BaseModel):
+ label: str
+ """Field label"""
+
+ name: str
+ """Field name"""
+
+ selector: str
+ """CSS selector for the field"""
+
+ type: Literal["text", "email", "password", "tel", "number", "url", "code", "checkbox"]
+ """Field type"""
+
+ placeholder: Optional[str] = None
+ """Field placeholder"""
+
+ required: Optional[bool] = None
+ """Whether field is required"""
diff --git a/tests/api_resources/agents/__init__.py b/tests/api_resources/agents/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/agents/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/agents/auth/__init__.py b/tests/api_resources/agents/auth/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/agents/auth/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/agents/auth/test_runs.py b/tests/api_resources/agents/auth/test_runs.py
new file mode 100644
index 00000000..25fbdb14
--- /dev/null
+++ b/tests/api_resources/agents/auth/test_runs.py
@@ -0,0 +1,401 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from kernel import Kernel, AsyncKernel
+from tests.utils import assert_matches_type
+from kernel.types.agents import AgentAuthRunResponse, AgentAuthSubmitResponse, AgentAuthDiscoverResponse
+from kernel.types.agents.auth import RunExchangeResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestRuns:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Kernel) -> None:
+ run = client.agents.auth.runs.retrieve(
+ "run_id",
+ )
+ assert_matches_type(AgentAuthRunResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Kernel) -> None:
+ response = client.agents.auth.runs.with_raw_response.retrieve(
+ "run_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = response.parse()
+ assert_matches_type(AgentAuthRunResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Kernel) -> None:
+ with client.agents.auth.runs.with_streaming_response.retrieve(
+ "run_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = response.parse()
+ assert_matches_type(AgentAuthRunResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ client.agents.auth.runs.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_discover(self, client: Kernel) -> None:
+ run = client.agents.auth.runs.discover(
+ "run_id",
+ )
+ assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_discover(self, client: Kernel) -> None:
+ response = client.agents.auth.runs.with_raw_response.discover(
+ "run_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = response.parse()
+ assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_discover(self, client: Kernel) -> None:
+ with client.agents.auth.runs.with_streaming_response.discover(
+ "run_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = response.parse()
+ assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_discover(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ client.agents.auth.runs.with_raw_response.discover(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_exchange(self, client: Kernel) -> None:
+ run = client.agents.auth.runs.exchange(
+ run_id="run_id",
+ code="otp_abc123xyz",
+ )
+ assert_matches_type(RunExchangeResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_exchange(self, client: Kernel) -> None:
+ response = client.agents.auth.runs.with_raw_response.exchange(
+ run_id="run_id",
+ code="otp_abc123xyz",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = response.parse()
+ assert_matches_type(RunExchangeResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_exchange(self, client: Kernel) -> None:
+ with client.agents.auth.runs.with_streaming_response.exchange(
+ run_id="run_id",
+ code="otp_abc123xyz",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = response.parse()
+ assert_matches_type(RunExchangeResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_exchange(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ client.agents.auth.runs.with_raw_response.exchange(
+ run_id="",
+ code="otp_abc123xyz",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_submit(self, client: Kernel) -> None:
+ run = client.agents.auth.runs.submit(
+ run_id="run_id",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ )
+ assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_submit(self, client: Kernel) -> None:
+ response = client.agents.auth.runs.with_raw_response.submit(
+ run_id="run_id",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = response.parse()
+ assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_submit(self, client: Kernel) -> None:
+ with client.agents.auth.runs.with_streaming_response.submit(
+ run_id="run_id",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = response.parse()
+ assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_submit(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ client.agents.auth.runs.with_raw_response.submit(
+ run_id="",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ )
+
+
+class TestAsyncRuns:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
+ run = await async_client.agents.auth.runs.retrieve(
+ "run_id",
+ )
+ assert_matches_type(AgentAuthRunResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
+ response = await async_client.agents.auth.runs.with_raw_response.retrieve(
+ "run_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = await response.parse()
+ assert_matches_type(AgentAuthRunResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
+ async with async_client.agents.auth.runs.with_streaming_response.retrieve(
+ "run_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = await response.parse()
+ assert_matches_type(AgentAuthRunResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ await async_client.agents.auth.runs.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_discover(self, async_client: AsyncKernel) -> None:
+ run = await async_client.agents.auth.runs.discover(
+ "run_id",
+ )
+ assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_discover(self, async_client: AsyncKernel) -> None:
+ response = await async_client.agents.auth.runs.with_raw_response.discover(
+ "run_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = await response.parse()
+ assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_discover(self, async_client: AsyncKernel) -> None:
+ async with async_client.agents.auth.runs.with_streaming_response.discover(
+ "run_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = await response.parse()
+ assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_discover(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ await async_client.agents.auth.runs.with_raw_response.discover(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_exchange(self, async_client: AsyncKernel) -> None:
+ run = await async_client.agents.auth.runs.exchange(
+ run_id="run_id",
+ code="otp_abc123xyz",
+ )
+ assert_matches_type(RunExchangeResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_exchange(self, async_client: AsyncKernel) -> None:
+ response = await async_client.agents.auth.runs.with_raw_response.exchange(
+ run_id="run_id",
+ code="otp_abc123xyz",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = await response.parse()
+ assert_matches_type(RunExchangeResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_exchange(self, async_client: AsyncKernel) -> None:
+ async with async_client.agents.auth.runs.with_streaming_response.exchange(
+ run_id="run_id",
+ code="otp_abc123xyz",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = await response.parse()
+ assert_matches_type(RunExchangeResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_exchange(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ await async_client.agents.auth.runs.with_raw_response.exchange(
+ run_id="",
+ code="otp_abc123xyz",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_submit(self, async_client: AsyncKernel) -> None:
+ run = await async_client.agents.auth.runs.submit(
+ run_id="run_id",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ )
+ assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_submit(self, async_client: AsyncKernel) -> None:
+ response = await async_client.agents.auth.runs.with_raw_response.submit(
+ run_id="run_id",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ run = await response.parse()
+ assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_submit(self, async_client: AsyncKernel) -> None:
+ async with async_client.agents.auth.runs.with_streaming_response.submit(
+ run_id="run_id",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ run = await response.parse()
+ assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_submit(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ await async_client.agents.auth.runs.with_raw_response.submit(
+ run_id="",
+ field_values={
+ "email": "user@example.com",
+ "password": "********",
+ },
+ )
diff --git a/tests/api_resources/agents/test_auth.py b/tests/api_resources/agents/test_auth.py
new file mode 100644
index 00000000..32d2784f
--- /dev/null
+++ b/tests/api_resources/agents/test_auth.py
@@ -0,0 +1,120 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from kernel import Kernel, AsyncKernel
+from tests.utils import assert_matches_type
+from kernel.types.agents import AgentAuthStartResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestAuth:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_start(self, client: Kernel) -> None:
+ auth = client.agents.auth.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ )
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_start_with_all_params(self, client: Kernel) -> None:
+ auth = client.agents.auth.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ app_logo_url="https://example.com/logo.png",
+ proxy={"proxy_id": "proxy_id"},
+ )
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_start(self, client: Kernel) -> None:
+ response = client.agents.auth.with_raw_response.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ auth = response.parse()
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_start(self, client: Kernel) -> None:
+ with client.agents.auth.with_streaming_response.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ auth = response.parse()
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncAuth:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_start(self, async_client: AsyncKernel) -> None:
+ auth = await async_client.agents.auth.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ )
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_start_with_all_params(self, async_client: AsyncKernel) -> None:
+ auth = await async_client.agents.auth.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ app_logo_url="https://example.com/logo.png",
+ proxy={"proxy_id": "proxy_id"},
+ )
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_start(self, async_client: AsyncKernel) -> None:
+ response = await async_client.agents.auth.with_raw_response.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ auth = await response.parse()
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_start(self, async_client: AsyncKernel) -> None:
+ async with async_client.agents.auth.with_streaming_response.start(
+ profile_name="auth-abc123",
+ target_domain="doordash.com",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ auth = await response.parse()
+ assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
From 97876e25f1a6286ca6e4167a1ea34698bece00c6 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 25 Nov 2025 18:13:27 +0000
Subject: [PATCH 03/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index bdbede3e..fa4f9006 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb3f37e55117a56e7a4208bd646d3a68adeb651ced8531e13fbfc1fc9dcb05a4.yml
-openapi_spec_hash: 7303ce8ce3130e16a6a5c2bb49e43e9b
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ae9ed0d949aa701dd3873e49080fe923404a8869ffcb69b7c912a3f244d0236d.yml
+openapi_spec_hash: 654d6e13a8bfe2103b373c668f43b33d
config_hash: be146470fb2d4583b6533859f0fa48f5
From a2f7605b72d38968fe83d6c7780956478812880a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 26 Nov 2025 00:27:26 +0000
Subject: [PATCH 04/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index fa4f9006..541095fa 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ae9ed0d949aa701dd3873e49080fe923404a8869ffcb69b7c912a3f244d0236d.yml
-openapi_spec_hash: 654d6e13a8bfe2103b373c668f43b33d
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a63841293bec1bb651c5a24a95b2e9b5c07851dec1164de1aa2f87dafc51046.yml
+openapi_spec_hash: d0bb3ca22c10b79758d503f717dd8e2f
config_hash: be146470fb2d4583b6533859f0fa48f5
From c82f496ba0112b195f65da9498fb22ab65d501fb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 28 Nov 2025 03:12:20 +0000
Subject: [PATCH 05/10] fix: ensure streams are always closed
---
src/kernel/_streaming.py | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/kernel/_streaming.py b/src/kernel/_streaming.py
index e6d03062..369a3f6d 100644
--- a/src/kernel/_streaming.py
+++ b/src/kernel/_streaming.py
@@ -54,11 +54,12 @@ def __stream__(self) -> Iterator[_T]:
process_data = self._client._process_response_data
iterator = self._iter_events()
- for sse in iterator:
- yield process_data(data=sse.json(), cast_to=cast_to, response=response)
-
- # As we might not fully consume the response stream, we need to close it explicitly
- response.close()
+ try:
+ for sse in iterator:
+ yield process_data(data=sse.json(), cast_to=cast_to, response=response)
+ finally:
+ # Ensure the response is closed even if the consumer doesn't read all data
+ response.close()
def __enter__(self) -> Self:
return self
@@ -117,11 +118,12 @@ async def __stream__(self) -> AsyncIterator[_T]:
process_data = self._client._process_response_data
iterator = self._iter_events()
- async for sse in iterator:
- yield process_data(data=sse.json(), cast_to=cast_to, response=response)
-
- # As we might not fully consume the response stream, we need to close it explicitly
- await response.aclose()
+ try:
+ async for sse in iterator:
+ yield process_data(data=sse.json(), cast_to=cast_to, response=response)
+ finally:
+ # Ensure the response is closed even if the consumer doesn't read all data
+ await response.aclose()
async def __aenter__(self) -> Self:
return self
From 038b10d52935961c37ebb0806e9b0754b4d53a20 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 28 Nov 2025 03:13:24 +0000
Subject: [PATCH 06/10] chore(deps): mypy 1.18.1 has a regression, pin to 1.17
---
pyproject.toml | 2 +-
requirements-dev.lock | 4 +++-
requirements.lock | 8 ++++----
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
index 43139568..71c4c9aa 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -46,7 +46,7 @@ managed = true
# version pins are in requirements-dev.lock
dev-dependencies = [
"pyright==1.1.399",
- "mypy",
+ "mypy==1.17",
"respx",
"pytest",
"pytest-asyncio",
diff --git a/requirements-dev.lock b/requirements-dev.lock
index fc032738..b435fc70 100644
--- a/requirements-dev.lock
+++ b/requirements-dev.lock
@@ -72,7 +72,7 @@ mdurl==0.1.2
multidict==6.4.4
# via aiohttp
# via yarl
-mypy==1.14.1
+mypy==1.17.0
mypy-extensions==1.0.0
# via mypy
nodeenv==1.8.0
@@ -81,6 +81,8 @@ nox==2023.4.22
packaging==23.2
# via nox
# via pytest
+pathspec==0.12.1
+ # via mypy
platformdirs==3.11.0
# via virtualenv
pluggy==1.5.0
diff --git a/requirements.lock b/requirements.lock
index ed64e3db..646e8cda 100644
--- a/requirements.lock
+++ b/requirements.lock
@@ -55,21 +55,21 @@ multidict==6.4.4
propcache==0.3.1
# via aiohttp
# via yarl
-pydantic==2.11.9
+pydantic==2.12.5
# via kernel
-pydantic-core==2.33.2
+pydantic-core==2.41.5
# via pydantic
sniffio==1.3.0
# via anyio
# via kernel
-typing-extensions==4.12.2
+typing-extensions==4.15.0
# via anyio
# via kernel
# via multidict
# via pydantic
# via pydantic-core
# via typing-inspection
-typing-inspection==0.4.1
+typing-inspection==0.4.2
# via pydantic
yarl==1.20.0
# via aiohttp
From 5a76df0f20dcc45f0e16a1f78766a3e5aeaf5537 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 01:22:10 +0000
Subject: [PATCH 07/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 541095fa..a6b35ee5 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a63841293bec1bb651c5a24a95b2e9b5c07851dec1164de1aa2f87dafc51046.yml
-openapi_spec_hash: d0bb3ca22c10b79758d503f717dd8e2f
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92b20a9e4650f645d3bb23b64f4ae72287bb41d3922ff1371426a91879186362.yml
+openapi_spec_hash: a3c5f41d36734c980bc5313ee60b97cf
config_hash: be146470fb2d4583b6533859f0fa48f5
From c2d7408a770ddd34902986015da0bfde3477f586 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 20:24:28 +0000
Subject: [PATCH 08/10] feat: Browser pools sdk release
---
.stats.yml | 8 +-
api.md | 54 +-
src/kernel/_client.py | 19 +-
src/kernel/resources/__init__.py | 28 +-
src/kernel/resources/agents/__init__.py | 33 -
src/kernel/resources/agents/agents.py | 102 --
src/kernel/resources/agents/auth/__init__.py | 33 -
src/kernel/resources/agents/auth/auth.py | 239 ----
src/kernel/resources/agents/auth/runs.py | 434 -------
src/kernel/resources/browser_pools.py | 1022 +++++++++++++++++
src/kernel/resources/browsers/browsers.py | 15 +-
src/kernel/types/__init__.py | 12 +
src/kernel/types/agents/__init__.py | 10 -
.../agents/agent_auth_discover_response.py | 28 -
.../types/agents/agent_auth_run_response.py | 22 -
.../types/agents/agent_auth_start_response.py | 21 -
.../agents/agent_auth_submit_response.py | 34 -
src/kernel/types/agents/auth/__init__.py | 7 -
.../types/agents/auth/run_exchange_params.py | 12 -
.../agents/auth/run_exchange_response.py | 13 -
.../types/agents/auth/run_submit_params.py | 13 -
src/kernel/types/agents/auth_start_params.py | 26 -
src/kernel/types/agents/discovered_field.py | 28 -
src/kernel/types/browser_create_params.py | 55 +-
src/kernel/types/browser_create_response.py | 19 +-
src/kernel/types/browser_list_response.py | 19 +-
src/kernel/types/browser_pool.py | 29 +
.../types/browser_pool_acquire_params.py | 16 +
.../types/browser_pool_acquire_response.py | 64 ++
.../types/browser_pool_create_params.py | 75 ++
.../types/browser_pool_delete_params.py | 15 +
.../types/browser_pool_list_response.py | 10 +
.../types/browser_pool_release_params.py | 18 +
src/kernel/types/browser_pool_request.py | 73 ++
.../types/browser_pool_update_params.py | 81 ++
src/kernel/types/browser_retrieve_response.py | 19 +-
src/kernel/types/shared/__init__.py | 3 +
src/kernel/types/shared/browser_extension.py | 18 +
src/kernel/types/shared/browser_profile.py | 24 +
src/kernel/types/shared/browser_viewport.py | 21 +
src/kernel/types/shared_params/__init__.py | 5 +
.../types/shared_params/browser_extension.py | 18 +
.../types/shared_params/browser_profile.py | 24 +
.../types/shared_params/browser_viewport.py | 21 +
tests/api_resources/agents/__init__.py | 1 -
tests/api_resources/agents/auth/__init__.py | 1 -
tests/api_resources/agents/auth/test_runs.py | 401 -------
tests/api_resources/agents/test_auth.py | 120 --
tests/api_resources/test_browser_pools.py | 856 ++++++++++++++
49 files changed, 2486 insertions(+), 1733 deletions(-)
delete mode 100644 src/kernel/resources/agents/__init__.py
delete mode 100644 src/kernel/resources/agents/agents.py
delete mode 100644 src/kernel/resources/agents/auth/__init__.py
delete mode 100644 src/kernel/resources/agents/auth/auth.py
delete mode 100644 src/kernel/resources/agents/auth/runs.py
create mode 100644 src/kernel/resources/browser_pools.py
delete mode 100644 src/kernel/types/agents/__init__.py
delete mode 100644 src/kernel/types/agents/agent_auth_discover_response.py
delete mode 100644 src/kernel/types/agents/agent_auth_run_response.py
delete mode 100644 src/kernel/types/agents/agent_auth_start_response.py
delete mode 100644 src/kernel/types/agents/agent_auth_submit_response.py
delete mode 100644 src/kernel/types/agents/auth/__init__.py
delete mode 100644 src/kernel/types/agents/auth/run_exchange_params.py
delete mode 100644 src/kernel/types/agents/auth/run_exchange_response.py
delete mode 100644 src/kernel/types/agents/auth/run_submit_params.py
delete mode 100644 src/kernel/types/agents/auth_start_params.py
delete mode 100644 src/kernel/types/agents/discovered_field.py
create mode 100644 src/kernel/types/browser_pool.py
create mode 100644 src/kernel/types/browser_pool_acquire_params.py
create mode 100644 src/kernel/types/browser_pool_acquire_response.py
create mode 100644 src/kernel/types/browser_pool_create_params.py
create mode 100644 src/kernel/types/browser_pool_delete_params.py
create mode 100644 src/kernel/types/browser_pool_list_response.py
create mode 100644 src/kernel/types/browser_pool_release_params.py
create mode 100644 src/kernel/types/browser_pool_request.py
create mode 100644 src/kernel/types/browser_pool_update_params.py
create mode 100644 src/kernel/types/shared/browser_extension.py
create mode 100644 src/kernel/types/shared/browser_profile.py
create mode 100644 src/kernel/types/shared/browser_viewport.py
create mode 100644 src/kernel/types/shared_params/__init__.py
create mode 100644 src/kernel/types/shared_params/browser_extension.py
create mode 100644 src/kernel/types/shared_params/browser_profile.py
create mode 100644 src/kernel/types/shared_params/browser_viewport.py
delete mode 100644 tests/api_resources/agents/__init__.py
delete mode 100644 tests/api_resources/agents/auth/__init__.py
delete mode 100644 tests/api_resources/agents/auth/test_runs.py
delete mode 100644 tests/api_resources/agents/test_auth.py
create mode 100644 tests/api_resources/test_browser_pools.py
diff --git a/.stats.yml b/.stats.yml
index a6b35ee5..c32f96db 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92b20a9e4650f645d3bb23b64f4ae72287bb41d3922ff1371426a91879186362.yml
-openapi_spec_hash: a3c5f41d36734c980bc5313ee60b97cf
-config_hash: be146470fb2d4583b6533859f0fa48f5
+configured_endpoints: 74
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-340c8f009b71922347d4c238c8715cd752c8965abfa12cbb1ffabe35edc338a8.yml
+openapi_spec_hash: efc13ab03ef89cc07333db8ab5345f31
+config_hash: a4124701ae0a474e580d7416adbcfb00
diff --git a/api.md b/api.md
index 483ff9cb..fe6b45c0 100644
--- a/api.md
+++ b/api.md
@@ -1,7 +1,17 @@
# Shared Types
```python
-from kernel.types import AppAction, ErrorDetail, ErrorEvent, ErrorModel, HeartbeatEvent, LogEvent
+from kernel.types import (
+ AppAction,
+ BrowserExtension,
+ BrowserProfile,
+ BrowserViewport,
+ ErrorDetail,
+ ErrorEvent,
+ ErrorModel,
+ HeartbeatEvent,
+ LogEvent,
+)
```
# Deployments
@@ -244,37 +254,29 @@ Methods:
- client.extensions.download_from_chrome_store(\*\*params) -> BinaryAPIResponse
- client.extensions.upload(\*\*params) -> ExtensionUploadResponse
-# Agents
-
-## Auth
+# BrowserPools
Types:
```python
-from kernel.types.agents import (
- AgentAuthDiscoverResponse,
- AgentAuthRunResponse,
- AgentAuthStartResponse,
- AgentAuthSubmitResponse,
- DiscoveredField,
+from kernel.types import (
+ BrowserPool,
+ BrowserPoolAcquireRequest,
+ BrowserPoolReleaseRequest,
+ BrowserPoolRequest,
+ BrowserPoolUpdateRequest,
+ BrowserPoolListResponse,
+ BrowserPoolAcquireResponse,
)
```
Methods:
-- client.agents.auth.start(\*\*params) -> AgentAuthStartResponse
-
-### Runs
-
-Types:
-
-```python
-from kernel.types.agents.auth import RunExchangeResponse
-```
-
-Methods:
-
-- client.agents.auth.runs.retrieve(run_id) -> AgentAuthRunResponse
-- client.agents.auth.runs.discover(run_id) -> AgentAuthDiscoverResponse
-- client.agents.auth.runs.exchange(run_id, \*\*params) -> RunExchangeResponse
-- client.agents.auth.runs.submit(run_id, \*\*params) -> AgentAuthSubmitResponse
+- client.browser_pools.create(\*\*params) -> BrowserPool
+- client.browser_pools.retrieve(id_or_name) -> BrowserPool
+- client.browser_pools.update(id_or_name, \*\*params) -> BrowserPool
+- client.browser_pools.list() -> BrowserPoolListResponse
+- client.browser_pools.delete(id_or_name, \*\*params) -> None
+- client.browser_pools.acquire(id_or_name, \*\*params) -> BrowserPoolAcquireResponse
+- client.browser_pools.flush(id_or_name) -> None
+- client.browser_pools.release(id_or_name, \*\*params) -> None
diff --git a/src/kernel/_client.py b/src/kernel/_client.py
index ba424335..37ba4890 100644
--- a/src/kernel/_client.py
+++ b/src/kernel/_client.py
@@ -21,7 +21,7 @@
)
from ._utils import is_given, get_async_library
from ._version import __version__
-from .resources import apps, proxies, profiles, extensions, deployments, invocations
+from .resources import apps, proxies, profiles, extensions, deployments, invocations, browser_pools
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import KernelError, APIStatusError
from ._base_client import (
@@ -29,7 +29,6 @@
SyncAPIClient,
AsyncAPIClient,
)
-from .resources.agents import agents
from .resources.browsers import browsers
__all__ = [
@@ -58,7 +57,7 @@ class Kernel(SyncAPIClient):
profiles: profiles.ProfilesResource
proxies: proxies.ProxiesResource
extensions: extensions.ExtensionsResource
- agents: agents.AgentsResource
+ browser_pools: browser_pools.BrowserPoolsResource
with_raw_response: KernelWithRawResponse
with_streaming_response: KernelWithStreamedResponse
@@ -147,7 +146,7 @@ def __init__(
self.profiles = profiles.ProfilesResource(self)
self.proxies = proxies.ProxiesResource(self)
self.extensions = extensions.ExtensionsResource(self)
- self.agents = agents.AgentsResource(self)
+ self.browser_pools = browser_pools.BrowserPoolsResource(self)
self.with_raw_response = KernelWithRawResponse(self)
self.with_streaming_response = KernelWithStreamedResponse(self)
@@ -266,7 +265,7 @@ class AsyncKernel(AsyncAPIClient):
profiles: profiles.AsyncProfilesResource
proxies: proxies.AsyncProxiesResource
extensions: extensions.AsyncExtensionsResource
- agents: agents.AsyncAgentsResource
+ browser_pools: browser_pools.AsyncBrowserPoolsResource
with_raw_response: AsyncKernelWithRawResponse
with_streaming_response: AsyncKernelWithStreamedResponse
@@ -355,7 +354,7 @@ def __init__(
self.profiles = profiles.AsyncProfilesResource(self)
self.proxies = proxies.AsyncProxiesResource(self)
self.extensions = extensions.AsyncExtensionsResource(self)
- self.agents = agents.AsyncAgentsResource(self)
+ self.browser_pools = browser_pools.AsyncBrowserPoolsResource(self)
self.with_raw_response = AsyncKernelWithRawResponse(self)
self.with_streaming_response = AsyncKernelWithStreamedResponse(self)
@@ -475,7 +474,7 @@ def __init__(self, client: Kernel) -> None:
self.profiles = profiles.ProfilesResourceWithRawResponse(client.profiles)
self.proxies = proxies.ProxiesResourceWithRawResponse(client.proxies)
self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions)
- self.agents = agents.AgentsResourceWithRawResponse(client.agents)
+ self.browser_pools = browser_pools.BrowserPoolsResourceWithRawResponse(client.browser_pools)
class AsyncKernelWithRawResponse:
@@ -487,7 +486,7 @@ def __init__(self, client: AsyncKernel) -> None:
self.profiles = profiles.AsyncProfilesResourceWithRawResponse(client.profiles)
self.proxies = proxies.AsyncProxiesResourceWithRawResponse(client.proxies)
self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions)
- self.agents = agents.AsyncAgentsResourceWithRawResponse(client.agents)
+ self.browser_pools = browser_pools.AsyncBrowserPoolsResourceWithRawResponse(client.browser_pools)
class KernelWithStreamedResponse:
@@ -499,7 +498,7 @@ def __init__(self, client: Kernel) -> None:
self.profiles = profiles.ProfilesResourceWithStreamingResponse(client.profiles)
self.proxies = proxies.ProxiesResourceWithStreamingResponse(client.proxies)
self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions)
- self.agents = agents.AgentsResourceWithStreamingResponse(client.agents)
+ self.browser_pools = browser_pools.BrowserPoolsResourceWithStreamingResponse(client.browser_pools)
class AsyncKernelWithStreamedResponse:
@@ -511,7 +510,7 @@ def __init__(self, client: AsyncKernel) -> None:
self.profiles = profiles.AsyncProfilesResourceWithStreamingResponse(client.profiles)
self.proxies = proxies.AsyncProxiesResourceWithStreamingResponse(client.proxies)
self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions)
- self.agents = agents.AsyncAgentsResourceWithStreamingResponse(client.agents)
+ self.browser_pools = browser_pools.AsyncBrowserPoolsResourceWithStreamingResponse(client.browser_pools)
Client = Kernel
diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py
index 233ef508..cf08046e 100644
--- a/src/kernel/resources/__init__.py
+++ b/src/kernel/resources/__init__.py
@@ -8,14 +8,6 @@
AppsResourceWithStreamingResponse,
AsyncAppsResourceWithStreamingResponse,
)
-from .agents import (
- AgentsResource,
- AsyncAgentsResource,
- AgentsResourceWithRawResponse,
- AsyncAgentsResourceWithRawResponse,
- AgentsResourceWithStreamingResponse,
- AsyncAgentsResourceWithStreamingResponse,
-)
from .proxies import (
ProxiesResource,
AsyncProxiesResource,
@@ -64,6 +56,14 @@
InvocationsResourceWithStreamingResponse,
AsyncInvocationsResourceWithStreamingResponse,
)
+from .browser_pools import (
+ BrowserPoolsResource,
+ AsyncBrowserPoolsResource,
+ BrowserPoolsResourceWithRawResponse,
+ AsyncBrowserPoolsResourceWithRawResponse,
+ BrowserPoolsResourceWithStreamingResponse,
+ AsyncBrowserPoolsResourceWithStreamingResponse,
+)
__all__ = [
"DeploymentsResource",
@@ -108,10 +108,10 @@
"AsyncExtensionsResourceWithRawResponse",
"ExtensionsResourceWithStreamingResponse",
"AsyncExtensionsResourceWithStreamingResponse",
- "AgentsResource",
- "AsyncAgentsResource",
- "AgentsResourceWithRawResponse",
- "AsyncAgentsResourceWithRawResponse",
- "AgentsResourceWithStreamingResponse",
- "AsyncAgentsResourceWithStreamingResponse",
+ "BrowserPoolsResource",
+ "AsyncBrowserPoolsResource",
+ "BrowserPoolsResourceWithRawResponse",
+ "AsyncBrowserPoolsResourceWithRawResponse",
+ "BrowserPoolsResourceWithStreamingResponse",
+ "AsyncBrowserPoolsResourceWithStreamingResponse",
]
diff --git a/src/kernel/resources/agents/__init__.py b/src/kernel/resources/agents/__init__.py
deleted file mode 100644
index cb159eb7..00000000
--- a/src/kernel/resources/agents/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .auth import (
- AuthResource,
- AsyncAuthResource,
- AuthResourceWithRawResponse,
- AsyncAuthResourceWithRawResponse,
- AuthResourceWithStreamingResponse,
- AsyncAuthResourceWithStreamingResponse,
-)
-from .agents import (
- AgentsResource,
- AsyncAgentsResource,
- AgentsResourceWithRawResponse,
- AsyncAgentsResourceWithRawResponse,
- AgentsResourceWithStreamingResponse,
- AsyncAgentsResourceWithStreamingResponse,
-)
-
-__all__ = [
- "AuthResource",
- "AsyncAuthResource",
- "AuthResourceWithRawResponse",
- "AsyncAuthResourceWithRawResponse",
- "AuthResourceWithStreamingResponse",
- "AsyncAuthResourceWithStreamingResponse",
- "AgentsResource",
- "AsyncAgentsResource",
- "AgentsResourceWithRawResponse",
- "AsyncAgentsResourceWithRawResponse",
- "AgentsResourceWithStreamingResponse",
- "AsyncAgentsResourceWithStreamingResponse",
-]
diff --git a/src/kernel/resources/agents/agents.py b/src/kernel/resources/agents/agents.py
deleted file mode 100644
index b7bb580c..00000000
--- a/src/kernel/resources/agents/agents.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from ..._compat import cached_property
-from .auth.auth import (
- AuthResource,
- AsyncAuthResource,
- AuthResourceWithRawResponse,
- AsyncAuthResourceWithRawResponse,
- AuthResourceWithStreamingResponse,
- AsyncAuthResourceWithStreamingResponse,
-)
-from ..._resource import SyncAPIResource, AsyncAPIResource
-
-__all__ = ["AgentsResource", "AsyncAgentsResource"]
-
-
-class AgentsResource(SyncAPIResource):
- @cached_property
- def auth(self) -> AuthResource:
- return AuthResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AgentsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
- """
- return AgentsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AgentsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
- """
- return AgentsResourceWithStreamingResponse(self)
-
-
-class AsyncAgentsResource(AsyncAPIResource):
- @cached_property
- def auth(self) -> AsyncAuthResource:
- return AsyncAuthResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncAgentsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
- """
- return AsyncAgentsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncAgentsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
- """
- return AsyncAgentsResourceWithStreamingResponse(self)
-
-
-class AgentsResourceWithRawResponse:
- def __init__(self, agents: AgentsResource) -> None:
- self._agents = agents
-
- @cached_property
- def auth(self) -> AuthResourceWithRawResponse:
- return AuthResourceWithRawResponse(self._agents.auth)
-
-
-class AsyncAgentsResourceWithRawResponse:
- def __init__(self, agents: AsyncAgentsResource) -> None:
- self._agents = agents
-
- @cached_property
- def auth(self) -> AsyncAuthResourceWithRawResponse:
- return AsyncAuthResourceWithRawResponse(self._agents.auth)
-
-
-class AgentsResourceWithStreamingResponse:
- def __init__(self, agents: AgentsResource) -> None:
- self._agents = agents
-
- @cached_property
- def auth(self) -> AuthResourceWithStreamingResponse:
- return AuthResourceWithStreamingResponse(self._agents.auth)
-
-
-class AsyncAgentsResourceWithStreamingResponse:
- def __init__(self, agents: AsyncAgentsResource) -> None:
- self._agents = agents
-
- @cached_property
- def auth(self) -> AsyncAuthResourceWithStreamingResponse:
- return AsyncAuthResourceWithStreamingResponse(self._agents.auth)
diff --git a/src/kernel/resources/agents/auth/__init__.py b/src/kernel/resources/agents/auth/__init__.py
deleted file mode 100644
index d9853204..00000000
--- a/src/kernel/resources/agents/auth/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .auth import (
- AuthResource,
- AsyncAuthResource,
- AuthResourceWithRawResponse,
- AsyncAuthResourceWithRawResponse,
- AuthResourceWithStreamingResponse,
- AsyncAuthResourceWithStreamingResponse,
-)
-from .runs import (
- RunsResource,
- AsyncRunsResource,
- RunsResourceWithRawResponse,
- AsyncRunsResourceWithRawResponse,
- RunsResourceWithStreamingResponse,
- AsyncRunsResourceWithStreamingResponse,
-)
-
-__all__ = [
- "RunsResource",
- "AsyncRunsResource",
- "RunsResourceWithRawResponse",
- "AsyncRunsResourceWithRawResponse",
- "RunsResourceWithStreamingResponse",
- "AsyncRunsResourceWithStreamingResponse",
- "AuthResource",
- "AsyncAuthResource",
- "AuthResourceWithRawResponse",
- "AsyncAuthResourceWithRawResponse",
- "AuthResourceWithStreamingResponse",
- "AsyncAuthResourceWithStreamingResponse",
-]
diff --git a/src/kernel/resources/agents/auth/auth.py b/src/kernel/resources/agents/auth/auth.py
deleted file mode 100644
index 2e099095..00000000
--- a/src/kernel/resources/agents/auth/auth.py
+++ /dev/null
@@ -1,239 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import httpx
-
-from .runs import (
- RunsResource,
- AsyncRunsResource,
- RunsResourceWithRawResponse,
- AsyncRunsResourceWithRawResponse,
- RunsResourceWithStreamingResponse,
- AsyncRunsResourceWithStreamingResponse,
-)
-from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ...._utils import maybe_transform, async_maybe_transform
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from ...._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...._base_client import make_request_options
-from ....types.agents import auth_start_params
-from ....types.agents.agent_auth_start_response import AgentAuthStartResponse
-
-__all__ = ["AuthResource", "AsyncAuthResource"]
-
-
-class AuthResource(SyncAPIResource):
- @cached_property
- def runs(self) -> RunsResource:
- return RunsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AuthResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
- """
- return AuthResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AuthResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
- """
- return AuthResourceWithStreamingResponse(self)
-
- def start(
- self,
- *,
- profile_name: str,
- target_domain: str,
- app_logo_url: str | Omit = omit,
- proxy: auth_start_params.Proxy | 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,
- ) -> AgentAuthStartResponse:
- """Creates a browser session and returns a handoff code for the hosted flow.
-
- Uses
- standard API key or JWT authentication (not the JWT returned by the exchange
- endpoint).
-
- Args:
- profile_name: Name of the profile to use for this flow
-
- target_domain: Target domain for authentication
-
- app_logo_url: Optional logo URL for the application
-
- proxy: Optional proxy configuration
-
- 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
- """
- return self._post(
- "/agents/auth/start",
- body=maybe_transform(
- {
- "profile_name": profile_name,
- "target_domain": target_domain,
- "app_logo_url": app_logo_url,
- "proxy": proxy,
- },
- auth_start_params.AuthStartParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthStartResponse,
- )
-
-
-class AsyncAuthResource(AsyncAPIResource):
- @cached_property
- def runs(self) -> AsyncRunsResource:
- return AsyncRunsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncAuthResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
- """
- return AsyncAuthResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncAuthResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
- """
- return AsyncAuthResourceWithStreamingResponse(self)
-
- async def start(
- self,
- *,
- profile_name: str,
- target_domain: str,
- app_logo_url: str | Omit = omit,
- proxy: auth_start_params.Proxy | 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,
- ) -> AgentAuthStartResponse:
- """Creates a browser session and returns a handoff code for the hosted flow.
-
- Uses
- standard API key or JWT authentication (not the JWT returned by the exchange
- endpoint).
-
- Args:
- profile_name: Name of the profile to use for this flow
-
- target_domain: Target domain for authentication
-
- app_logo_url: Optional logo URL for the application
-
- proxy: Optional proxy configuration
-
- 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
- """
- return await self._post(
- "/agents/auth/start",
- body=await async_maybe_transform(
- {
- "profile_name": profile_name,
- "target_domain": target_domain,
- "app_logo_url": app_logo_url,
- "proxy": proxy,
- },
- auth_start_params.AuthStartParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthStartResponse,
- )
-
-
-class AuthResourceWithRawResponse:
- def __init__(self, auth: AuthResource) -> None:
- self._auth = auth
-
- self.start = to_raw_response_wrapper(
- auth.start,
- )
-
- @cached_property
- def runs(self) -> RunsResourceWithRawResponse:
- return RunsResourceWithRawResponse(self._auth.runs)
-
-
-class AsyncAuthResourceWithRawResponse:
- def __init__(self, auth: AsyncAuthResource) -> None:
- self._auth = auth
-
- self.start = async_to_raw_response_wrapper(
- auth.start,
- )
-
- @cached_property
- def runs(self) -> AsyncRunsResourceWithRawResponse:
- return AsyncRunsResourceWithRawResponse(self._auth.runs)
-
-
-class AuthResourceWithStreamingResponse:
- def __init__(self, auth: AuthResource) -> None:
- self._auth = auth
-
- self.start = to_streamed_response_wrapper(
- auth.start,
- )
-
- @cached_property
- def runs(self) -> RunsResourceWithStreamingResponse:
- return RunsResourceWithStreamingResponse(self._auth.runs)
-
-
-class AsyncAuthResourceWithStreamingResponse:
- def __init__(self, auth: AsyncAuthResource) -> None:
- self._auth = auth
-
- self.start = async_to_streamed_response_wrapper(
- auth.start,
- )
-
- @cached_property
- def runs(self) -> AsyncRunsResourceWithStreamingResponse:
- return AsyncRunsResourceWithStreamingResponse(self._auth.runs)
diff --git a/src/kernel/resources/agents/auth/runs.py b/src/kernel/resources/agents/auth/runs.py
deleted file mode 100644
index 6ea09403..00000000
--- a/src/kernel/resources/agents/auth/runs.py
+++ /dev/null
@@ -1,434 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Dict
-
-import httpx
-
-from ...._types import Body, Query, Headers, NotGiven, not_given
-from ...._utils import maybe_transform, async_maybe_transform
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from ...._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...._base_client import make_request_options
-from ....types.agents.auth import run_submit_params, run_exchange_params
-from ....types.agents.agent_auth_run_response import AgentAuthRunResponse
-from ....types.agents.agent_auth_submit_response import AgentAuthSubmitResponse
-from ....types.agents.auth.run_exchange_response import RunExchangeResponse
-from ....types.agents.agent_auth_discover_response import AgentAuthDiscoverResponse
-
-__all__ = ["RunsResource", "AsyncRunsResource"]
-
-
-class RunsResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> RunsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
- """
- return RunsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> RunsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
- """
- return RunsResourceWithStreamingResponse(self)
-
- def retrieve(
- self,
- run_id: str,
- *,
- # 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,
- ) -> AgentAuthRunResponse:
- """Returns run details including app_name and target_domain.
-
- Uses the JWT returned
- by the exchange endpoint, or standard API key or JWT authentication.
-
- Args:
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return self._get(
- f"/agents/auth/runs/{run_id}",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthRunResponse,
- )
-
- def discover(
- self,
- run_id: str,
- *,
- # 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,
- ) -> AgentAuthDiscoverResponse:
- """
- Inspects the target site to detect logged-in state or discover required fields.
- Returns 200 with success: true when fields are found, or 4xx/5xx for failures.
- Requires the JWT returned by the exchange endpoint.
-
- Args:
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return self._post(
- f"/agents/auth/runs/{run_id}/discover",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthDiscoverResponse,
- )
-
- def exchange(
- self,
- run_id: str,
- *,
- code: str,
- # 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,
- ) -> RunExchangeResponse:
- """Validates the handoff code and returns a JWT token for subsequent requests.
-
- No
- authentication required (the handoff code serves as the credential).
-
- Args:
- code: Handoff code from start endpoint
-
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return self._post(
- f"/agents/auth/runs/{run_id}/exchange",
- body=maybe_transform({"code": code}, run_exchange_params.RunExchangeParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=RunExchangeResponse,
- )
-
- def submit(
- self,
- run_id: str,
- *,
- field_values: Dict[str, str],
- # 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,
- ) -> AgentAuthSubmitResponse:
- """
- Submits field values for the discovered login form and may return additional
- auth fields or success. Requires the JWT returned by the exchange endpoint.
-
- Args:
- field_values: Values for the discovered login fields
-
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return self._post(
- f"/agents/auth/runs/{run_id}/submit",
- body=maybe_transform({"field_values": field_values}, run_submit_params.RunSubmitParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthSubmitResponse,
- )
-
-
-class AsyncRunsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncRunsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
- """
- return AsyncRunsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncRunsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
- """
- return AsyncRunsResourceWithStreamingResponse(self)
-
- async def retrieve(
- self,
- run_id: str,
- *,
- # 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,
- ) -> AgentAuthRunResponse:
- """Returns run details including app_name and target_domain.
-
- Uses the JWT returned
- by the exchange endpoint, or standard API key or JWT authentication.
-
- Args:
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return await self._get(
- f"/agents/auth/runs/{run_id}",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthRunResponse,
- )
-
- async def discover(
- self,
- run_id: str,
- *,
- # 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,
- ) -> AgentAuthDiscoverResponse:
- """
- Inspects the target site to detect logged-in state or discover required fields.
- Returns 200 with success: true when fields are found, or 4xx/5xx for failures.
- Requires the JWT returned by the exchange endpoint.
-
- Args:
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return await self._post(
- f"/agents/auth/runs/{run_id}/discover",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthDiscoverResponse,
- )
-
- async def exchange(
- self,
- run_id: str,
- *,
- code: str,
- # 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,
- ) -> RunExchangeResponse:
- """Validates the handoff code and returns a JWT token for subsequent requests.
-
- No
- authentication required (the handoff code serves as the credential).
-
- Args:
- code: Handoff code from start endpoint
-
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return await self._post(
- f"/agents/auth/runs/{run_id}/exchange",
- body=await async_maybe_transform({"code": code}, run_exchange_params.RunExchangeParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=RunExchangeResponse,
- )
-
- async def submit(
- self,
- run_id: str,
- *,
- field_values: Dict[str, str],
- # 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,
- ) -> AgentAuthSubmitResponse:
- """
- Submits field values for the discovered login form and may return additional
- auth fields or success. Requires the JWT returned by the exchange endpoint.
-
- Args:
- field_values: Values for the discovered login fields
-
- 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
- """
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return await self._post(
- f"/agents/auth/runs/{run_id}/submit",
- body=await async_maybe_transform({"field_values": field_values}, run_submit_params.RunSubmitParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AgentAuthSubmitResponse,
- )
-
-
-class RunsResourceWithRawResponse:
- def __init__(self, runs: RunsResource) -> None:
- self._runs = runs
-
- self.retrieve = to_raw_response_wrapper(
- runs.retrieve,
- )
- self.discover = to_raw_response_wrapper(
- runs.discover,
- )
- self.exchange = to_raw_response_wrapper(
- runs.exchange,
- )
- self.submit = to_raw_response_wrapper(
- runs.submit,
- )
-
-
-class AsyncRunsResourceWithRawResponse:
- def __init__(self, runs: AsyncRunsResource) -> None:
- self._runs = runs
-
- self.retrieve = async_to_raw_response_wrapper(
- runs.retrieve,
- )
- self.discover = async_to_raw_response_wrapper(
- runs.discover,
- )
- self.exchange = async_to_raw_response_wrapper(
- runs.exchange,
- )
- self.submit = async_to_raw_response_wrapper(
- runs.submit,
- )
-
-
-class RunsResourceWithStreamingResponse:
- def __init__(self, runs: RunsResource) -> None:
- self._runs = runs
-
- self.retrieve = to_streamed_response_wrapper(
- runs.retrieve,
- )
- self.discover = to_streamed_response_wrapper(
- runs.discover,
- )
- self.exchange = to_streamed_response_wrapper(
- runs.exchange,
- )
- self.submit = to_streamed_response_wrapper(
- runs.submit,
- )
-
-
-class AsyncRunsResourceWithStreamingResponse:
- def __init__(self, runs: AsyncRunsResource) -> None:
- self._runs = runs
-
- self.retrieve = async_to_streamed_response_wrapper(
- runs.retrieve,
- )
- self.discover = async_to_streamed_response_wrapper(
- runs.discover,
- )
- self.exchange = async_to_streamed_response_wrapper(
- runs.exchange,
- )
- self.submit = async_to_streamed_response_wrapper(
- runs.submit,
- )
diff --git a/src/kernel/resources/browser_pools.py b/src/kernel/resources/browser_pools.py
new file mode 100644
index 00000000..d085d515
--- /dev/null
+++ b/src/kernel/resources/browser_pools.py
@@ -0,0 +1,1022 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+
+import httpx
+
+from ..types import (
+ browser_pool_create_params,
+ browser_pool_delete_params,
+ browser_pool_update_params,
+ browser_pool_acquire_params,
+ browser_pool_release_params,
+)
+from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+from ..types.browser_pool import BrowserPool
+from ..types.browser_pool_list_response import BrowserPoolListResponse
+from ..types.browser_pool_acquire_response import BrowserPoolAcquireResponse
+from ..types.shared_params.browser_profile import BrowserProfile
+from ..types.shared_params.browser_viewport import BrowserViewport
+from ..types.shared_params.browser_extension import BrowserExtension
+
+__all__ = ["BrowserPoolsResource", "AsyncBrowserPoolsResource"]
+
+
+class BrowserPoolsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> BrowserPoolsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return BrowserPoolsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> BrowserPoolsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return BrowserPoolsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ size: int,
+ extensions: Iterable[BrowserExtension] | Omit = omit,
+ fill_rate_per_minute: int | Omit = omit,
+ headless: bool | Omit = omit,
+ kiosk_mode: bool | Omit = omit,
+ name: str | Omit = omit,
+ profile: BrowserProfile | Omit = omit,
+ proxy_id: str | Omit = omit,
+ stealth: bool | Omit = omit,
+ timeout_seconds: int | Omit = omit,
+ viewport: BrowserViewport | 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,
+ ) -> BrowserPool:
+ """
+ Create a new browser pool with the specified configuration and size.
+
+ Args:
+ size: Number of browsers to create in the pool
+
+ 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%.
+
+ headless: If true, launches the browser using a headless image. Defaults to false.
+
+ kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ view.
+
+ name: Optional name for the browser pool. Must be unique within the organization.
+
+ profile: Profile selection for the browser session. Provide either id or name. If
+ specified, the matching profile will be loaded into the browser session.
+ Profiles must be created beforehand.
+
+ proxy_id: Optional proxy to associate to the browser session. Must reference a proxy
+ belonging to the caller's org.
+
+ stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot
+ 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
+
+ viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
+ image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+
+ 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
+ """
+ return self._post(
+ "/browser_pools",
+ body=maybe_transform(
+ {
+ "size": size,
+ "extensions": extensions,
+ "fill_rate_per_minute": fill_rate_per_minute,
+ "headless": headless,
+ "kiosk_mode": kiosk_mode,
+ "name": name,
+ "profile": profile,
+ "proxy_id": proxy_id,
+ "stealth": stealth,
+ "timeout_seconds": timeout_seconds,
+ "viewport": viewport,
+ },
+ browser_pool_create_params.BrowserPoolCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPool,
+ )
+
+ def retrieve(
+ self,
+ id_or_name: str,
+ *,
+ # 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,
+ ) -> BrowserPool:
+ """
+ Retrieve details for a single browser pool by its ID or name.
+
+ Args:
+ 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
+ """
+ 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._get(
+ f"/browser_pools/{id_or_name}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPool,
+ )
+
+ def update(
+ self,
+ id_or_name: str,
+ *,
+ size: int,
+ discard_all_idle: bool | Omit = omit,
+ extensions: Iterable[BrowserExtension] | Omit = omit,
+ fill_rate_per_minute: int | Omit = omit,
+ headless: bool | Omit = omit,
+ kiosk_mode: bool | Omit = omit,
+ name: str | Omit = omit,
+ profile: BrowserProfile | Omit = omit,
+ proxy_id: str | Omit = omit,
+ stealth: bool | Omit = omit,
+ timeout_seconds: int | Omit = omit,
+ viewport: BrowserViewport | 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,
+ ) -> BrowserPool:
+ """
+ Updates the configuration used to create browsers in the pool.
+
+ Args:
+ size: Number of browsers to create in the pool
+
+ discard_all_idle: Whether to discard all idle browsers and rebuild the pool immediately. Defaults
+ to true.
+
+ 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%.
+
+ headless: If true, launches the browser using a headless image. Defaults to false.
+
+ kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ view.
+
+ name: Optional name for the browser pool. Must be unique within the organization.
+
+ profile: Profile selection for the browser session. Provide either id or name. If
+ specified, the matching profile will be loaded into the browser session.
+ Profiles must be created beforehand.
+
+ proxy_id: Optional proxy to associate to the browser session. Must reference a proxy
+ belonging to the caller's org.
+
+ stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot
+ 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
+
+ viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
+ image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+
+ 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
+ """
+ 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._patch(
+ f"/browser_pools/{id_or_name}",
+ body=maybe_transform(
+ {
+ "size": size,
+ "discard_all_idle": discard_all_idle,
+ "extensions": extensions,
+ "fill_rate_per_minute": fill_rate_per_minute,
+ "headless": headless,
+ "kiosk_mode": kiosk_mode,
+ "name": name,
+ "profile": profile,
+ "proxy_id": proxy_id,
+ "stealth": stealth,
+ "timeout_seconds": timeout_seconds,
+ "viewport": viewport,
+ },
+ browser_pool_update_params.BrowserPoolUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPool,
+ )
+
+ def list(
+ self,
+ *,
+ # 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,
+ ) -> BrowserPoolListResponse:
+ """List browser pools owned by the caller's organization."""
+ return self._get(
+ "/browser_pools",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPoolListResponse,
+ )
+
+ def delete(
+ self,
+ id_or_name: str,
+ *,
+ force: bool | 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,
+ ) -> None:
+ """Delete a browser pool and all browsers in it.
+
+ By default, deletion is blocked if
+ browsers are currently leased. Use force=true to terminate leased browsers.
+
+ Args:
+ force: If true, force delete even if browsers are currently leased. Leased browsers
+ will be terminated.
+
+ 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._delete(
+ f"/browser_pools/{id_or_name}",
+ body=maybe_transform({"force": force}, browser_pool_delete_params.BrowserPoolDeleteParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def acquire(
+ self,
+ id_or_name: str,
+ *,
+ acquire_timeout_seconds: int | 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,
+ ) -> BrowserPoolAcquireResponse:
+ """Long-polling endpoint to acquire a browser from the pool.
+
+ Returns immediately
+ when a browser is available, or returns 204 No Content when the poll times out.
+ The client should retry the request to continue waiting for a browser. The
+ acquired browser will use the pool's timeout_seconds for its idle timeout.
+
+ Args:
+ acquire_timeout_seconds: Maximum number of seconds to wait for a browser to be available. Defaults to the
+ calculated time it would take to fill the pool at the currently configured fill
+ rate.
+
+ 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
+ """
+ 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(
+ f"/browser_pools/{id_or_name}/acquire",
+ body=maybe_transform(
+ {"acquire_timeout_seconds": acquire_timeout_seconds},
+ browser_pool_acquire_params.BrowserPoolAcquireParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPoolAcquireResponse,
+ )
+
+ def flush(
+ self,
+ id_or_name: str,
+ *,
+ # 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,
+ ) -> None:
+ """
+ Destroys all idle browsers in the pool; leased browsers are not affected.
+
+ Args:
+ 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browser_pools/{id_or_name}/flush",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def release(
+ self,
+ id_or_name: str,
+ *,
+ session_id: str,
+ reuse: bool | 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,
+ ) -> None:
+ """
+ Release a browser back to the pool, optionally recreating the browser instance.
+
+ Args:
+ session_id: Browser session ID to release back to the pool
+
+ reuse: Whether to reuse the browser instance or destroy it and create a new one.
+ Defaults to true.
+
+ 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browser_pools/{id_or_name}/release",
+ body=maybe_transform(
+ {
+ "session_id": session_id,
+ "reuse": reuse,
+ },
+ browser_pool_release_params.BrowserPoolReleaseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+
+class AsyncBrowserPoolsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncBrowserPoolsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AsyncBrowserPoolsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncBrowserPoolsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response
+ """
+ return AsyncBrowserPoolsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ size: int,
+ extensions: Iterable[BrowserExtension] | Omit = omit,
+ fill_rate_per_minute: int | Omit = omit,
+ headless: bool | Omit = omit,
+ kiosk_mode: bool | Omit = omit,
+ name: str | Omit = omit,
+ profile: BrowserProfile | Omit = omit,
+ proxy_id: str | Omit = omit,
+ stealth: bool | Omit = omit,
+ timeout_seconds: int | Omit = omit,
+ viewport: BrowserViewport | 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,
+ ) -> BrowserPool:
+ """
+ Create a new browser pool with the specified configuration and size.
+
+ Args:
+ size: Number of browsers to create in the pool
+
+ 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%.
+
+ headless: If true, launches the browser using a headless image. Defaults to false.
+
+ kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ view.
+
+ name: Optional name for the browser pool. Must be unique within the organization.
+
+ profile: Profile selection for the browser session. Provide either id or name. If
+ specified, the matching profile will be loaded into the browser session.
+ Profiles must be created beforehand.
+
+ proxy_id: Optional proxy to associate to the browser session. Must reference a proxy
+ belonging to the caller's org.
+
+ stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot
+ 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
+
+ viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
+ image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+
+ 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
+ """
+ return await self._post(
+ "/browser_pools",
+ body=await async_maybe_transform(
+ {
+ "size": size,
+ "extensions": extensions,
+ "fill_rate_per_minute": fill_rate_per_minute,
+ "headless": headless,
+ "kiosk_mode": kiosk_mode,
+ "name": name,
+ "profile": profile,
+ "proxy_id": proxy_id,
+ "stealth": stealth,
+ "timeout_seconds": timeout_seconds,
+ "viewport": viewport,
+ },
+ browser_pool_create_params.BrowserPoolCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPool,
+ )
+
+ async def retrieve(
+ self,
+ id_or_name: str,
+ *,
+ # 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,
+ ) -> BrowserPool:
+ """
+ Retrieve details for a single browser pool by its ID or name.
+
+ Args:
+ 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
+ """
+ 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._get(
+ f"/browser_pools/{id_or_name}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPool,
+ )
+
+ async def update(
+ self,
+ id_or_name: str,
+ *,
+ size: int,
+ discard_all_idle: bool | Omit = omit,
+ extensions: Iterable[BrowserExtension] | Omit = omit,
+ fill_rate_per_minute: int | Omit = omit,
+ headless: bool | Omit = omit,
+ kiosk_mode: bool | Omit = omit,
+ name: str | Omit = omit,
+ profile: BrowserProfile | Omit = omit,
+ proxy_id: str | Omit = omit,
+ stealth: bool | Omit = omit,
+ timeout_seconds: int | Omit = omit,
+ viewport: BrowserViewport | 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,
+ ) -> BrowserPool:
+ """
+ Updates the configuration used to create browsers in the pool.
+
+ Args:
+ size: Number of browsers to create in the pool
+
+ discard_all_idle: Whether to discard all idle browsers and rebuild the pool immediately. Defaults
+ to true.
+
+ 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%.
+
+ headless: If true, launches the browser using a headless image. Defaults to false.
+
+ kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ view.
+
+ name: Optional name for the browser pool. Must be unique within the organization.
+
+ profile: Profile selection for the browser session. Provide either id or name. If
+ specified, the matching profile will be loaded into the browser session.
+ Profiles must be created beforehand.
+
+ proxy_id: Optional proxy to associate to the browser session. Must reference a proxy
+ belonging to the caller's org.
+
+ stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot
+ 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
+
+ viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
+ image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+
+ 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
+ """
+ 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._patch(
+ f"/browser_pools/{id_or_name}",
+ body=await async_maybe_transform(
+ {
+ "size": size,
+ "discard_all_idle": discard_all_idle,
+ "extensions": extensions,
+ "fill_rate_per_minute": fill_rate_per_minute,
+ "headless": headless,
+ "kiosk_mode": kiosk_mode,
+ "name": name,
+ "profile": profile,
+ "proxy_id": proxy_id,
+ "stealth": stealth,
+ "timeout_seconds": timeout_seconds,
+ "viewport": viewport,
+ },
+ browser_pool_update_params.BrowserPoolUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPool,
+ )
+
+ async def list(
+ self,
+ *,
+ # 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,
+ ) -> BrowserPoolListResponse:
+ """List browser pools owned by the caller's organization."""
+ return await self._get(
+ "/browser_pools",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPoolListResponse,
+ )
+
+ async def delete(
+ self,
+ id_or_name: str,
+ *,
+ force: bool | 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,
+ ) -> None:
+ """Delete a browser pool and all browsers in it.
+
+ By default, deletion is blocked if
+ browsers are currently leased. Use force=true to terminate leased browsers.
+
+ Args:
+ force: If true, force delete even if browsers are currently leased. Leased browsers
+ will be terminated.
+
+ 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._delete(
+ f"/browser_pools/{id_or_name}",
+ body=await async_maybe_transform({"force": force}, browser_pool_delete_params.BrowserPoolDeleteParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def acquire(
+ self,
+ id_or_name: str,
+ *,
+ acquire_timeout_seconds: int | 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,
+ ) -> BrowserPoolAcquireResponse:
+ """Long-polling endpoint to acquire a browser from the pool.
+
+ Returns immediately
+ when a browser is available, or returns 204 No Content when the poll times out.
+ The client should retry the request to continue waiting for a browser. The
+ acquired browser will use the pool's timeout_seconds for its idle timeout.
+
+ Args:
+ acquire_timeout_seconds: Maximum number of seconds to wait for a browser to be available. Defaults to the
+ calculated time it would take to fill the pool at the currently configured fill
+ rate.
+
+ 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
+ """
+ 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(
+ f"/browser_pools/{id_or_name}/acquire",
+ body=await async_maybe_transform(
+ {"acquire_timeout_seconds": acquire_timeout_seconds},
+ browser_pool_acquire_params.BrowserPoolAcquireParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BrowserPoolAcquireResponse,
+ )
+
+ async def flush(
+ self,
+ id_or_name: str,
+ *,
+ # 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,
+ ) -> None:
+ """
+ Destroys all idle browsers in the pool; leased browsers are not affected.
+
+ Args:
+ 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browser_pools/{id_or_name}/flush",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def release(
+ self,
+ id_or_name: str,
+ *,
+ session_id: str,
+ reuse: bool | 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,
+ ) -> None:
+ """
+ Release a browser back to the pool, optionally recreating the browser instance.
+
+ Args:
+ session_id: Browser session ID to release back to the pool
+
+ reuse: Whether to reuse the browser instance or destroy it and create a new one.
+ Defaults to true.
+
+ 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browser_pools/{id_or_name}/release",
+ body=await async_maybe_transform(
+ {
+ "session_id": session_id,
+ "reuse": reuse,
+ },
+ browser_pool_release_params.BrowserPoolReleaseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+
+class BrowserPoolsResourceWithRawResponse:
+ def __init__(self, browser_pools: BrowserPoolsResource) -> None:
+ self._browser_pools = browser_pools
+
+ self.create = to_raw_response_wrapper(
+ browser_pools.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ browser_pools.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ browser_pools.update,
+ )
+ self.list = to_raw_response_wrapper(
+ browser_pools.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ browser_pools.delete,
+ )
+ self.acquire = to_raw_response_wrapper(
+ browser_pools.acquire,
+ )
+ self.flush = to_raw_response_wrapper(
+ browser_pools.flush,
+ )
+ self.release = to_raw_response_wrapper(
+ browser_pools.release,
+ )
+
+
+class AsyncBrowserPoolsResourceWithRawResponse:
+ def __init__(self, browser_pools: AsyncBrowserPoolsResource) -> None:
+ self._browser_pools = browser_pools
+
+ self.create = async_to_raw_response_wrapper(
+ browser_pools.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ browser_pools.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ browser_pools.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ browser_pools.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ browser_pools.delete,
+ )
+ self.acquire = async_to_raw_response_wrapper(
+ browser_pools.acquire,
+ )
+ self.flush = async_to_raw_response_wrapper(
+ browser_pools.flush,
+ )
+ self.release = async_to_raw_response_wrapper(
+ browser_pools.release,
+ )
+
+
+class BrowserPoolsResourceWithStreamingResponse:
+ def __init__(self, browser_pools: BrowserPoolsResource) -> None:
+ self._browser_pools = browser_pools
+
+ self.create = to_streamed_response_wrapper(
+ browser_pools.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ browser_pools.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ browser_pools.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ browser_pools.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ browser_pools.delete,
+ )
+ self.acquire = to_streamed_response_wrapper(
+ browser_pools.acquire,
+ )
+ self.flush = to_streamed_response_wrapper(
+ browser_pools.flush,
+ )
+ self.release = to_streamed_response_wrapper(
+ browser_pools.release,
+ )
+
+
+class AsyncBrowserPoolsResourceWithStreamingResponse:
+ def __init__(self, browser_pools: AsyncBrowserPoolsResource) -> None:
+ self._browser_pools = browser_pools
+
+ self.create = async_to_streamed_response_wrapper(
+ browser_pools.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ browser_pools.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ browser_pools.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ browser_pools.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ browser_pools.delete,
+ )
+ self.acquire = async_to_streamed_response_wrapper(
+ browser_pools.acquire,
+ )
+ self.flush = async_to_streamed_response_wrapper(
+ browser_pools.flush,
+ )
+ self.release = async_to_streamed_response_wrapper(
+ browser_pools.release,
+ )
diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py
index 84a4fe48..f41b46ad 100644
--- a/src/kernel/resources/browsers/browsers.py
+++ b/src/kernel/resources/browsers/browsers.py
@@ -76,6 +76,9 @@
from ...types.browser_create_response import BrowserCreateResponse
from ...types.browser_persistence_param import BrowserPersistenceParam
from ...types.browser_retrieve_response import BrowserRetrieveResponse
+from ...types.shared_params.browser_profile import BrowserProfile
+from ...types.shared_params.browser_viewport import BrowserViewport
+from ...types.shared_params.browser_extension import BrowserExtension
__all__ = ["BrowsersResource", "AsyncBrowsersResource"]
@@ -127,16 +130,16 @@ def with_streaming_response(self) -> BrowsersResourceWithStreamingResponse:
def create(
self,
*,
- extensions: Iterable[browser_create_params.Extension] | Omit = omit,
+ extensions: Iterable[BrowserExtension] | Omit = omit,
headless: bool | Omit = omit,
invocation_id: str | Omit = omit,
kiosk_mode: bool | Omit = omit,
persistence: BrowserPersistenceParam | Omit = omit,
- profile: browser_create_params.Profile | Omit = omit,
+ profile: BrowserProfile | Omit = omit,
proxy_id: str | Omit = omit,
stealth: bool | Omit = omit,
timeout_seconds: int | Omit = omit,
- viewport: browser_create_params.Viewport | Omit = omit,
+ viewport: BrowserViewport | 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,
@@ -470,16 +473,16 @@ def with_streaming_response(self) -> AsyncBrowsersResourceWithStreamingResponse:
async def create(
self,
*,
- extensions: Iterable[browser_create_params.Extension] | Omit = omit,
+ extensions: Iterable[BrowserExtension] | Omit = omit,
headless: bool | Omit = omit,
invocation_id: str | Omit = omit,
kiosk_mode: bool | Omit = omit,
persistence: BrowserPersistenceParam | Omit = omit,
- profile: browser_create_params.Profile | Omit = omit,
+ profile: BrowserProfile | Omit = omit,
proxy_id: str | Omit = omit,
stealth: bool | Omit = omit,
timeout_seconds: int | Omit = omit,
- viewport: browser_create_params.Viewport | Omit = omit,
+ viewport: BrowserViewport | 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/kernel/types/__init__.py b/src/kernel/types/__init__.py
index 208a8bda..45b0c4ba 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -8,15 +8,20 @@
ErrorEvent as ErrorEvent,
ErrorModel as ErrorModel,
ErrorDetail as ErrorDetail,
+ BrowserProfile as BrowserProfile,
HeartbeatEvent as HeartbeatEvent,
+ BrowserViewport as BrowserViewport,
+ BrowserExtension as BrowserExtension,
)
from .profile import Profile as Profile
+from .browser_pool import BrowserPool as BrowserPool
from .app_list_params import AppListParams as AppListParams
from .app_list_response import AppListResponse as AppListResponse
from .browser_list_params import BrowserListParams as BrowserListParams
from .browser_persistence import BrowserPersistence as BrowserPersistence
from .proxy_create_params import ProxyCreateParams as ProxyCreateParams
from .proxy_list_response import ProxyListResponse as ProxyListResponse
+from .browser_pool_request import BrowserPoolRequest as BrowserPoolRequest
from .browser_create_params import BrowserCreateParams as BrowserCreateParams
from .browser_delete_params import BrowserDeleteParams as BrowserDeleteParams
from .browser_list_response import BrowserListResponse as BrowserListResponse
@@ -41,13 +46,20 @@
from .browser_persistence_param import BrowserPersistenceParam as BrowserPersistenceParam
from .browser_retrieve_response import BrowserRetrieveResponse as BrowserRetrieveResponse
from .extension_upload_response import ExtensionUploadResponse as ExtensionUploadResponse
+from .browser_pool_create_params import BrowserPoolCreateParams as BrowserPoolCreateParams
+from .browser_pool_delete_params import BrowserPoolDeleteParams as BrowserPoolDeleteParams
+from .browser_pool_list_response import BrowserPoolListResponse as BrowserPoolListResponse
+from .browser_pool_update_params import BrowserPoolUpdateParams as BrowserPoolUpdateParams
from .deployment_create_response import DeploymentCreateResponse as DeploymentCreateResponse
from .deployment_follow_response import DeploymentFollowResponse as DeploymentFollowResponse
from .invocation_create_response import InvocationCreateResponse as InvocationCreateResponse
from .invocation_follow_response import InvocationFollowResponse as InvocationFollowResponse
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 .deployment_retrieve_response import DeploymentRetrieveResponse as DeploymentRetrieveResponse
from .invocation_retrieve_response import InvocationRetrieveResponse as InvocationRetrieveResponse
+from .browser_pool_acquire_response import BrowserPoolAcquireResponse as BrowserPoolAcquireResponse
from .browser_load_extensions_params import BrowserLoadExtensionsParams as BrowserLoadExtensionsParams
from .extension_download_from_chrome_store_params import (
ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams,
diff --git a/src/kernel/types/agents/__init__.py b/src/kernel/types/agents/__init__.py
deleted file mode 100644
index e8c22774..00000000
--- a/src/kernel/types/agents/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .discovered_field import DiscoveredField as DiscoveredField
-from .auth_start_params import AuthStartParams as AuthStartParams
-from .agent_auth_run_response import AgentAuthRunResponse as AgentAuthRunResponse
-from .agent_auth_start_response import AgentAuthStartResponse as AgentAuthStartResponse
-from .agent_auth_submit_response import AgentAuthSubmitResponse as AgentAuthSubmitResponse
-from .agent_auth_discover_response import AgentAuthDiscoverResponse as AgentAuthDiscoverResponse
diff --git a/src/kernel/types/agents/agent_auth_discover_response.py b/src/kernel/types/agents/agent_auth_discover_response.py
deleted file mode 100644
index 000bdec2..00000000
--- a/src/kernel/types/agents/agent_auth_discover_response.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from ..._models import BaseModel
-from .discovered_field import DiscoveredField
-
-__all__ = ["AgentAuthDiscoverResponse"]
-
-
-class AgentAuthDiscoverResponse(BaseModel):
- success: bool
- """Whether discovery succeeded"""
-
- error_message: Optional[str] = None
- """Error message if discovery failed"""
-
- fields: Optional[List[DiscoveredField]] = None
- """Discovered form fields (present when success is true)"""
-
- logged_in: Optional[bool] = None
- """Whether user is already logged in"""
-
- login_url: Optional[str] = None
- """URL of the discovered login page"""
-
- page_title: Optional[str] = None
- """Title of the login page"""
diff --git a/src/kernel/types/agents/agent_auth_run_response.py b/src/kernel/types/agents/agent_auth_run_response.py
deleted file mode 100644
index 0ec0b0bb..00000000
--- a/src/kernel/types/agents/agent_auth_run_response.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from datetime import datetime
-from typing_extensions import Literal
-
-from ..._models import BaseModel
-
-__all__ = ["AgentAuthRunResponse"]
-
-
-class AgentAuthRunResponse(BaseModel):
- app_name: str
- """App name (org name at time of run creation)"""
-
- expires_at: datetime
- """When the handoff code expires"""
-
- status: Literal["ACTIVE", "ENDED", "EXPIRED", "CANCELED"]
- """Run status"""
-
- target_domain: str
- """Target domain for authentication"""
diff --git a/src/kernel/types/agents/agent_auth_start_response.py b/src/kernel/types/agents/agent_auth_start_response.py
deleted file mode 100644
index 2855fc2d..00000000
--- a/src/kernel/types/agents/agent_auth_start_response.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from datetime import datetime
-
-from ..._models import BaseModel
-
-__all__ = ["AgentAuthStartResponse"]
-
-
-class AgentAuthStartResponse(BaseModel):
- expires_at: datetime
- """When the handoff code expires"""
-
- handoff_code: str
- """One-time code for handoff"""
-
- hosted_url: str
- """URL to redirect user to"""
-
- run_id: str
- """Unique identifier for the run"""
diff --git a/src/kernel/types/agents/agent_auth_submit_response.py b/src/kernel/types/agents/agent_auth_submit_response.py
deleted file mode 100644
index c57002fb..00000000
--- a/src/kernel/types/agents/agent_auth_submit_response.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from ..._models import BaseModel
-from .discovered_field import DiscoveredField
-
-__all__ = ["AgentAuthSubmitResponse"]
-
-
-class AgentAuthSubmitResponse(BaseModel):
- success: bool
- """Whether submission succeeded"""
-
- additional_fields: Optional[List[DiscoveredField]] = None
- """
- Additional fields needed (e.g., OTP) - present when needs_additional_auth is
- true
- """
-
- app_name: Optional[str] = None
- """App name (only present when logged_in is true)"""
-
- error_message: Optional[str] = None
- """Error message if submission failed"""
-
- logged_in: Optional[bool] = None
- """Whether user is now logged in"""
-
- needs_additional_auth: Optional[bool] = None
- """Whether additional authentication fields are needed"""
-
- target_domain: Optional[str] = None
- """Target domain (only present when logged_in is true)"""
diff --git a/src/kernel/types/agents/auth/__init__.py b/src/kernel/types/agents/auth/__init__.py
deleted file mode 100644
index 78a13a38..00000000
--- a/src/kernel/types/agents/auth/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .run_submit_params import RunSubmitParams as RunSubmitParams
-from .run_exchange_params import RunExchangeParams as RunExchangeParams
-from .run_exchange_response import RunExchangeResponse as RunExchangeResponse
diff --git a/src/kernel/types/agents/auth/run_exchange_params.py b/src/kernel/types/agents/auth/run_exchange_params.py
deleted file mode 100644
index 1a23b25d..00000000
--- a/src/kernel/types/agents/auth/run_exchange_params.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-__all__ = ["RunExchangeParams"]
-
-
-class RunExchangeParams(TypedDict, total=False):
- code: Required[str]
- """Handoff code from start endpoint"""
diff --git a/src/kernel/types/agents/auth/run_exchange_response.py b/src/kernel/types/agents/auth/run_exchange_response.py
deleted file mode 100644
index 347c57c3..00000000
--- a/src/kernel/types/agents/auth/run_exchange_response.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from ...._models import BaseModel
-
-__all__ = ["RunExchangeResponse"]
-
-
-class RunExchangeResponse(BaseModel):
- jwt: str
- """JWT token with run_id claim (30 minute TTL)"""
-
- run_id: str
- """Run ID"""
diff --git a/src/kernel/types/agents/auth/run_submit_params.py b/src/kernel/types/agents/auth/run_submit_params.py
deleted file mode 100644
index efaf9ea5..00000000
--- a/src/kernel/types/agents/auth/run_submit_params.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Dict
-from typing_extensions import Required, TypedDict
-
-__all__ = ["RunSubmitParams"]
-
-
-class RunSubmitParams(TypedDict, total=False):
- field_values: Required[Dict[str, str]]
- """Values for the discovered login fields"""
diff --git a/src/kernel/types/agents/auth_start_params.py b/src/kernel/types/agents/auth_start_params.py
deleted file mode 100644
index 6e0f0c82..00000000
--- a/src/kernel/types/agents/auth_start_params.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-__all__ = ["AuthStartParams", "Proxy"]
-
-
-class AuthStartParams(TypedDict, total=False):
- profile_name: Required[str]
- """Name of the profile to use for this flow"""
-
- target_domain: Required[str]
- """Target domain for authentication"""
-
- app_logo_url: str
- """Optional logo URL for the application"""
-
- proxy: Proxy
- """Optional proxy configuration"""
-
-
-class Proxy(TypedDict, total=False):
- proxy_id: str
- """ID of the proxy to use"""
diff --git a/src/kernel/types/agents/discovered_field.py b/src/kernel/types/agents/discovered_field.py
deleted file mode 100644
index 90a4864c..00000000
--- a/src/kernel/types/agents/discovered_field.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-from typing_extensions import Literal
-
-from ..._models import BaseModel
-
-__all__ = ["DiscoveredField"]
-
-
-class DiscoveredField(BaseModel):
- label: str
- """Field label"""
-
- name: str
- """Field name"""
-
- selector: str
- """CSS selector for the field"""
-
- type: Literal["text", "email", "password", "tel", "number", "url", "code", "checkbox"]
- """Field type"""
-
- placeholder: Optional[str] = None
- """Field placeholder"""
-
- required: Optional[bool] = None
- """Whether field is required"""
diff --git a/src/kernel/types/browser_create_params.py b/src/kernel/types/browser_create_params.py
index 1e54ce75..d1ff7907 100644
--- a/src/kernel/types/browser_create_params.py
+++ b/src/kernel/types/browser_create_params.py
@@ -3,15 +3,18 @@
from __future__ import annotations
from typing import Iterable
-from typing_extensions import Required, TypedDict
+from typing_extensions import TypedDict
from .browser_persistence_param import BrowserPersistenceParam
+from .shared_params.browser_profile import BrowserProfile
+from .shared_params.browser_viewport import BrowserViewport
+from .shared_params.browser_extension import BrowserExtension
-__all__ = ["BrowserCreateParams", "Extension", "Profile", "Viewport"]
+__all__ = ["BrowserCreateParams"]
class BrowserCreateParams(TypedDict, total=False):
- extensions: Iterable[Extension]
+ extensions: Iterable[BrowserExtension]
"""List of browser extensions to load into the session.
Provide each by id or name.
@@ -35,7 +38,7 @@ class BrowserCreateParams(TypedDict, total=False):
persistence: BrowserPersistenceParam
"""Optional persistence configuration for the browser session."""
- profile: Profile
+ profile: BrowserProfile
"""Profile selection for the browser session.
Provide either id or name. If specified, the matching profile will be loaded
@@ -64,7 +67,7 @@ class BrowserCreateParams(TypedDict, total=False):
specified value.
"""
- viewport: Viewport
+ viewport: BrowserViewport
"""Initial browser window size in pixels with optional refresh rate.
If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
@@ -75,45 +78,3 @@ class BrowserCreateParams(TypedDict, total=False):
configuration exactly. Note: Higher resolutions may affect the responsiveness of
live view browser
"""
-
-
-class Extension(TypedDict, total=False):
- id: str
- """Extension ID to load for this browser session"""
-
- name: str
- """Extension name to load for this browser session (instead of id).
-
- Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
- """
-
-
-class Profile(TypedDict, total=False):
- id: str
- """Profile ID to load for this browser session"""
-
- name: str
- """Profile name to load for this browser session (instead of id).
-
- Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
- """
-
- save_changes: bool
- """
- If true, save changes made during the session back to the profile when the
- session ends.
- """
-
-
-class Viewport(TypedDict, total=False):
- height: Required[int]
- """Browser window height in pixels."""
-
- width: Required[int]
- """Browser window width in pixels."""
-
- refresh_rate: int
- """Display refresh rate in Hz.
-
- If omitted, automatically determined from width and height.
- """
diff --git a/src/kernel/types/browser_create_response.py b/src/kernel/types/browser_create_response.py
index 21041eaa..0a5f33d4 100644
--- a/src/kernel/types/browser_create_response.py
+++ b/src/kernel/types/browser_create_response.py
@@ -6,22 +6,9 @@
from .profile import Profile
from .._models import BaseModel
from .browser_persistence import BrowserPersistence
+from .shared.browser_viewport import BrowserViewport
-__all__ = ["BrowserCreateResponse", "Viewport"]
-
-
-class Viewport(BaseModel):
- height: int
- """Browser window height in pixels."""
-
- width: int
- """Browser window width in pixels."""
-
- refresh_rate: Optional[int] = None
- """Display refresh rate in Hz.
-
- If omitted, automatically determined from width and height.
- """
+__all__ = ["BrowserCreateResponse"]
class BrowserCreateResponse(BaseModel):
@@ -64,7 +51,7 @@ class BrowserCreateResponse(BaseModel):
proxy_id: Optional[str] = None
"""ID of the proxy associated with this browser session, if any."""
- viewport: Optional[Viewport] = None
+ viewport: Optional[BrowserViewport] = None
"""Initial browser window size in pixels with optional refresh rate.
If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
diff --git a/src/kernel/types/browser_list_response.py b/src/kernel/types/browser_list_response.py
index 74978690..d6397291 100644
--- a/src/kernel/types/browser_list_response.py
+++ b/src/kernel/types/browser_list_response.py
@@ -6,22 +6,9 @@
from .profile import Profile
from .._models import BaseModel
from .browser_persistence import BrowserPersistence
+from .shared.browser_viewport import BrowserViewport
-__all__ = ["BrowserListResponse", "Viewport"]
-
-
-class Viewport(BaseModel):
- height: int
- """Browser window height in pixels."""
-
- width: int
- """Browser window width in pixels."""
-
- refresh_rate: Optional[int] = None
- """Display refresh rate in Hz.
-
- If omitted, automatically determined from width and height.
- """
+__all__ = ["BrowserListResponse"]
class BrowserListResponse(BaseModel):
@@ -64,7 +51,7 @@ class BrowserListResponse(BaseModel):
proxy_id: Optional[str] = None
"""ID of the proxy associated with this browser session, if any."""
- viewport: Optional[Viewport] = None
+ viewport: Optional[BrowserViewport] = None
"""Initial browser window size in pixels with optional refresh rate.
If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
diff --git a/src/kernel/types/browser_pool.py b/src/kernel/types/browser_pool.py
new file mode 100644
index 00000000..5fd30dca
--- /dev/null
+++ b/src/kernel/types/browser_pool.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from .._models import BaseModel
+from .browser_pool_request import BrowserPoolRequest
+
+__all__ = ["BrowserPool"]
+
+
+class BrowserPool(BaseModel):
+ id: str
+ """Unique identifier for the browser pool"""
+
+ acquired_count: int
+ """Number of browsers currently acquired from the pool"""
+
+ available_count: int
+ """Number of browsers currently available in the pool"""
+
+ browser_pool_config: BrowserPoolRequest
+ """Configuration used to create all browsers in this pool"""
+
+ created_at: datetime
+ """Timestamp when the browser pool was created"""
+
+ name: Optional[str] = None
+ """Browser pool name, if set"""
diff --git a/src/kernel/types/browser_pool_acquire_params.py b/src/kernel/types/browser_pool_acquire_params.py
new file mode 100644
index 00000000..d0df921a
--- /dev/null
+++ b/src/kernel/types/browser_pool_acquire_params.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["BrowserPoolAcquireParams"]
+
+
+class BrowserPoolAcquireParams(TypedDict, total=False):
+ acquire_timeout_seconds: int
+ """Maximum number of seconds to wait for a browser to be available.
+
+ Defaults to the calculated time it would take to fill the pool at the currently
+ configured fill rate.
+ """
diff --git a/src/kernel/types/browser_pool_acquire_response.py b/src/kernel/types/browser_pool_acquire_response.py
new file mode 100644
index 00000000..76ad037b
--- /dev/null
+++ b/src/kernel/types/browser_pool_acquire_response.py
@@ -0,0 +1,64 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from .profile import Profile
+from .._models import BaseModel
+from .browser_persistence import BrowserPersistence
+from .shared.browser_viewport import BrowserViewport
+
+__all__ = ["BrowserPoolAcquireResponse"]
+
+
+class BrowserPoolAcquireResponse(BaseModel):
+ cdp_ws_url: str
+ """Websocket URL for Chrome DevTools Protocol connections to the browser session"""
+
+ created_at: datetime
+ """When the browser session was created."""
+
+ headless: bool
+ """Whether the browser session is running in headless mode."""
+
+ session_id: str
+ """Unique identifier for the browser session"""
+
+ stealth: bool
+ """Whether the browser session is running in stealth mode."""
+
+ timeout_seconds: int
+ """The number of seconds of inactivity before the browser session is terminated."""
+
+ browser_live_view_url: Optional[str] = None
+ """Remote URL for live viewing the browser session.
+
+ Only available for non-headless browsers.
+ """
+
+ deleted_at: Optional[datetime] = None
+ """When the browser session was soft-deleted. Only present for deleted sessions."""
+
+ kiosk_mode: Optional[bool] = None
+ """Whether the browser session is running in kiosk mode."""
+
+ persistence: Optional[BrowserPersistence] = None
+ """Optional persistence configuration for the browser session."""
+
+ profile: Optional[Profile] = None
+ """Browser profile metadata."""
+
+ proxy_id: Optional[str] = None
+ """ID of the proxy associated with this browser session, if any."""
+
+ viewport: Optional[BrowserViewport] = None
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
diff --git a/src/kernel/types/browser_pool_create_params.py b/src/kernel/types/browser_pool_create_params.py
new file mode 100644
index 00000000..c7f87c64
--- /dev/null
+++ b/src/kernel/types/browser_pool_create_params.py
@@ -0,0 +1,75 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+from .shared_params.browser_profile import BrowserProfile
+from .shared_params.browser_viewport import BrowserViewport
+from .shared_params.browser_extension import BrowserExtension
+
+__all__ = ["BrowserPoolCreateParams"]
+
+
+class BrowserPoolCreateParams(TypedDict, total=False):
+ size: Required[int]
+ """Number of browsers to create in the pool"""
+
+ extensions: Iterable[BrowserExtension]
+ """List of browser extensions to load into the session.
+
+ Provide each by id or name.
+ """
+
+ fill_rate_per_minute: int
+ """Percentage of the pool to fill per minute. Defaults to 10%."""
+
+ headless: bool
+ """If true, launches the browser using a headless image. Defaults to false."""
+
+ kiosk_mode: bool
+ """
+ If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ view.
+ """
+
+ name: str
+ """Optional name for the browser pool. Must be unique within the organization."""
+
+ profile: BrowserProfile
+ """Profile selection for the browser session.
+
+ Provide either id or name. If specified, the matching profile will be loaded
+ into the browser session. Profiles must be created beforehand.
+ """
+
+ proxy_id: str
+ """Optional proxy to associate to the browser session.
+
+ Must reference a proxy belonging to the caller's org.
+ """
+
+ stealth: bool
+ """
+ If true, launches the browser in stealth mode to reduce detection by anti-bot
+ mechanisms.
+ """
+
+ 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
+ """
+
+ viewport: BrowserViewport
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
diff --git a/src/kernel/types/browser_pool_delete_params.py b/src/kernel/types/browser_pool_delete_params.py
new file mode 100644
index 00000000..0a63c0f1
--- /dev/null
+++ b/src/kernel/types/browser_pool_delete_params.py
@@ -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__ = ["BrowserPoolDeleteParams"]
+
+
+class BrowserPoolDeleteParams(TypedDict, total=False):
+ force: bool
+ """If true, force delete even if browsers are currently leased.
+
+ Leased browsers will be terminated.
+ """
diff --git a/src/kernel/types/browser_pool_list_response.py b/src/kernel/types/browser_pool_list_response.py
new file mode 100644
index 00000000..a11c4de2
--- /dev/null
+++ b/src/kernel/types/browser_pool_list_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+from typing_extensions import TypeAlias
+
+from .browser_pool import BrowserPool
+
+__all__ = ["BrowserPoolListResponse"]
+
+BrowserPoolListResponse: TypeAlias = List[BrowserPool]
diff --git a/src/kernel/types/browser_pool_release_params.py b/src/kernel/types/browser_pool_release_params.py
new file mode 100644
index 00000000..104b0b0c
--- /dev/null
+++ b/src/kernel/types/browser_pool_release_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 Required, TypedDict
+
+__all__ = ["BrowserPoolReleaseParams"]
+
+
+class BrowserPoolReleaseParams(TypedDict, total=False):
+ session_id: Required[str]
+ """Browser session ID to release back to the pool"""
+
+ reuse: bool
+ """Whether to reuse the browser instance or destroy it and create a new one.
+
+ Defaults to true.
+ """
diff --git a/src/kernel/types/browser_pool_request.py b/src/kernel/types/browser_pool_request.py
new file mode 100644
index 00000000..c25b3a55
--- /dev/null
+++ b/src/kernel/types/browser_pool_request.py
@@ -0,0 +1,73 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+from .shared.browser_profile import BrowserProfile
+from .shared.browser_viewport import BrowserViewport
+from .shared.browser_extension import BrowserExtension
+
+__all__ = ["BrowserPoolRequest"]
+
+
+class BrowserPoolRequest(BaseModel):
+ size: int
+ """Number of browsers to create in the pool"""
+
+ extensions: Optional[List[BrowserExtension]] = None
+ """List of browser extensions to load into the session.
+
+ Provide each by id or name.
+ """
+
+ fill_rate_per_minute: Optional[int] = None
+ """Percentage of the pool to fill per minute. Defaults to 10%."""
+
+ headless: Optional[bool] = None
+ """If true, launches the browser using a headless image. Defaults to false."""
+
+ kiosk_mode: Optional[bool] = None
+ """
+ If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ view.
+ """
+
+ name: Optional[str] = None
+ """Optional name for the browser pool. Must be unique within the organization."""
+
+ profile: Optional[BrowserProfile] = None
+ """Profile selection for the browser session.
+
+ Provide either id or name. If specified, the matching profile will be loaded
+ into the browser session. Profiles must be created beforehand.
+ """
+
+ proxy_id: Optional[str] = None
+ """Optional proxy to associate to the browser session.
+
+ Must reference a proxy belonging to the caller's org.
+ """
+
+ stealth: Optional[bool] = None
+ """
+ If true, launches the browser in stealth mode to reduce detection by anti-bot
+ mechanisms.
+ """
+
+ 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
+ """
+
+ viewport: Optional[BrowserViewport] = None
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
diff --git a/src/kernel/types/browser_pool_update_params.py b/src/kernel/types/browser_pool_update_params.py
new file mode 100644
index 00000000..ed9a7e84
--- /dev/null
+++ b/src/kernel/types/browser_pool_update_params.py
@@ -0,0 +1,81 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+from .shared_params.browser_profile import BrowserProfile
+from .shared_params.browser_viewport import BrowserViewport
+from .shared_params.browser_extension import BrowserExtension
+
+__all__ = ["BrowserPoolUpdateParams"]
+
+
+class BrowserPoolUpdateParams(TypedDict, total=False):
+ size: Required[int]
+ """Number of browsers to create in the pool"""
+
+ discard_all_idle: bool
+ """Whether to discard all idle browsers and rebuild the pool immediately.
+
+ Defaults to true.
+ """
+
+ extensions: Iterable[BrowserExtension]
+ """List of browser extensions to load into the session.
+
+ Provide each by id or name.
+ """
+
+ fill_rate_per_minute: int
+ """Percentage of the pool to fill per minute. Defaults to 10%."""
+
+ headless: bool
+ """If true, launches the browser using a headless image. Defaults to false."""
+
+ kiosk_mode: bool
+ """
+ If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ view.
+ """
+
+ name: str
+ """Optional name for the browser pool. Must be unique within the organization."""
+
+ profile: BrowserProfile
+ """Profile selection for the browser session.
+
+ Provide either id or name. If specified, the matching profile will be loaded
+ into the browser session. Profiles must be created beforehand.
+ """
+
+ proxy_id: str
+ """Optional proxy to associate to the browser session.
+
+ Must reference a proxy belonging to the caller's org.
+ """
+
+ stealth: bool
+ """
+ If true, launches the browser in stealth mode to reduce detection by anti-bot
+ mechanisms.
+ """
+
+ 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
+ """
+
+ viewport: BrowserViewport
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ be automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
diff --git a/src/kernel/types/browser_retrieve_response.py b/src/kernel/types/browser_retrieve_response.py
index 527386da..111149b3 100644
--- a/src/kernel/types/browser_retrieve_response.py
+++ b/src/kernel/types/browser_retrieve_response.py
@@ -6,22 +6,9 @@
from .profile import Profile
from .._models import BaseModel
from .browser_persistence import BrowserPersistence
+from .shared.browser_viewport import BrowserViewport
-__all__ = ["BrowserRetrieveResponse", "Viewport"]
-
-
-class Viewport(BaseModel):
- height: int
- """Browser window height in pixels."""
-
- width: int
- """Browser window width in pixels."""
-
- refresh_rate: Optional[int] = None
- """Display refresh rate in Hz.
-
- If omitted, automatically determined from width and height.
- """
+__all__ = ["BrowserRetrieveResponse"]
class BrowserRetrieveResponse(BaseModel):
@@ -64,7 +51,7 @@ class BrowserRetrieveResponse(BaseModel):
proxy_id: Optional[str] = None
"""ID of the proxy associated with this browser session, if any."""
- viewport: Optional[Viewport] = None
+ viewport: Optional[BrowserViewport] = None
"""Initial browser window size in pixels with optional refresh rate.
If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
diff --git a/src/kernel/types/shared/__init__.py b/src/kernel/types/shared/__init__.py
index ea360f12..6b649199 100644
--- a/src/kernel/types/shared/__init__.py
+++ b/src/kernel/types/shared/__init__.py
@@ -5,4 +5,7 @@
from .error_event import ErrorEvent as ErrorEvent
from .error_model import ErrorModel as ErrorModel
from .error_detail import ErrorDetail as ErrorDetail
+from .browser_profile import BrowserProfile as BrowserProfile
from .heartbeat_event import HeartbeatEvent as HeartbeatEvent
+from .browser_viewport import BrowserViewport as BrowserViewport
+from .browser_extension import BrowserExtension as BrowserExtension
diff --git a/src/kernel/types/shared/browser_extension.py b/src/kernel/types/shared/browser_extension.py
new file mode 100644
index 00000000..7bc1a5ff
--- /dev/null
+++ b/src/kernel/types/shared/browser_extension.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["BrowserExtension"]
+
+
+class BrowserExtension(BaseModel):
+ id: Optional[str] = None
+ """Extension ID to load for this browser session"""
+
+ name: Optional[str] = None
+ """Extension name to load for this browser session (instead of id).
+
+ Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
+ """
diff --git a/src/kernel/types/shared/browser_profile.py b/src/kernel/types/shared/browser_profile.py
new file mode 100644
index 00000000..5f790ccb
--- /dev/null
+++ b/src/kernel/types/shared/browser_profile.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["BrowserProfile"]
+
+
+class BrowserProfile(BaseModel):
+ id: Optional[str] = None
+ """Profile ID to load for this browser session"""
+
+ name: Optional[str] = None
+ """Profile name to load for this browser session (instead of id).
+
+ Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
+ """
+
+ save_changes: Optional[bool] = None
+ """
+ If true, save changes made during the session back to the profile when the
+ session ends.
+ """
diff --git a/src/kernel/types/shared/browser_viewport.py b/src/kernel/types/shared/browser_viewport.py
new file mode 100644
index 00000000..abffcc29
--- /dev/null
+++ b/src/kernel/types/shared/browser_viewport.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["BrowserViewport"]
+
+
+class BrowserViewport(BaseModel):
+ height: int
+ """Browser window height in pixels."""
+
+ width: int
+ """Browser window width in pixels."""
+
+ refresh_rate: Optional[int] = None
+ """Display refresh rate in Hz.
+
+ If omitted, automatically determined from width and height.
+ """
diff --git a/src/kernel/types/shared_params/__init__.py b/src/kernel/types/shared_params/__init__.py
new file mode 100644
index 00000000..de63c649
--- /dev/null
+++ b/src/kernel/types/shared_params/__init__.py
@@ -0,0 +1,5 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .browser_profile import BrowserProfile as BrowserProfile
+from .browser_viewport import BrowserViewport as BrowserViewport
+from .browser_extension import BrowserExtension as BrowserExtension
diff --git a/src/kernel/types/shared_params/browser_extension.py b/src/kernel/types/shared_params/browser_extension.py
new file mode 100644
index 00000000..d81ac708
--- /dev/null
+++ b/src/kernel/types/shared_params/browser_extension.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__ = ["BrowserExtension"]
+
+
+class BrowserExtension(TypedDict, total=False):
+ id: str
+ """Extension ID to load for this browser session"""
+
+ name: str
+ """Extension name to load for this browser session (instead of id).
+
+ Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
+ """
diff --git a/src/kernel/types/shared_params/browser_profile.py b/src/kernel/types/shared_params/browser_profile.py
new file mode 100644
index 00000000..e1027d22
--- /dev/null
+++ b/src/kernel/types/shared_params/browser_profile.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["BrowserProfile"]
+
+
+class BrowserProfile(TypedDict, total=False):
+ id: str
+ """Profile ID to load for this browser session"""
+
+ name: str
+ """Profile name to load for this browser session (instead of id).
+
+ Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
+ """
+
+ save_changes: bool
+ """
+ If true, save changes made during the session back to the profile when the
+ session ends.
+ """
diff --git a/src/kernel/types/shared_params/browser_viewport.py b/src/kernel/types/shared_params/browser_viewport.py
new file mode 100644
index 00000000..b7cb2f0f
--- /dev/null
+++ b/src/kernel/types/shared_params/browser_viewport.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["BrowserViewport"]
+
+
+class BrowserViewport(TypedDict, total=False):
+ height: Required[int]
+ """Browser window height in pixels."""
+
+ width: Required[int]
+ """Browser window width in pixels."""
+
+ refresh_rate: int
+ """Display refresh rate in Hz.
+
+ If omitted, automatically determined from width and height.
+ """
diff --git a/tests/api_resources/agents/__init__.py b/tests/api_resources/agents/__init__.py
deleted file mode 100644
index fd8019a9..00000000
--- a/tests/api_resources/agents/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/agents/auth/__init__.py b/tests/api_resources/agents/auth/__init__.py
deleted file mode 100644
index fd8019a9..00000000
--- a/tests/api_resources/agents/auth/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/agents/auth/test_runs.py b/tests/api_resources/agents/auth/test_runs.py
deleted file mode 100644
index 25fbdb14..00000000
--- a/tests/api_resources/agents/auth/test_runs.py
+++ /dev/null
@@ -1,401 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from kernel import Kernel, AsyncKernel
-from tests.utils import assert_matches_type
-from kernel.types.agents import AgentAuthRunResponse, AgentAuthSubmitResponse, AgentAuthDiscoverResponse
-from kernel.types.agents.auth import RunExchangeResponse
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestRuns:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve(self, client: Kernel) -> None:
- run = client.agents.auth.runs.retrieve(
- "run_id",
- )
- assert_matches_type(AgentAuthRunResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_retrieve(self, client: Kernel) -> None:
- response = client.agents.auth.runs.with_raw_response.retrieve(
- "run_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = response.parse()
- assert_matches_type(AgentAuthRunResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_retrieve(self, client: Kernel) -> None:
- with client.agents.auth.runs.with_streaming_response.retrieve(
- "run_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = response.parse()
- assert_matches_type(AgentAuthRunResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_retrieve(self, client: Kernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- client.agents.auth.runs.with_raw_response.retrieve(
- "",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_discover(self, client: Kernel) -> None:
- run = client.agents.auth.runs.discover(
- "run_id",
- )
- assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_discover(self, client: Kernel) -> None:
- response = client.agents.auth.runs.with_raw_response.discover(
- "run_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = response.parse()
- assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_discover(self, client: Kernel) -> None:
- with client.agents.auth.runs.with_streaming_response.discover(
- "run_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = response.parse()
- assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_discover(self, client: Kernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- client.agents.auth.runs.with_raw_response.discover(
- "",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_exchange(self, client: Kernel) -> None:
- run = client.agents.auth.runs.exchange(
- run_id="run_id",
- code="otp_abc123xyz",
- )
- assert_matches_type(RunExchangeResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_exchange(self, client: Kernel) -> None:
- response = client.agents.auth.runs.with_raw_response.exchange(
- run_id="run_id",
- code="otp_abc123xyz",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = response.parse()
- assert_matches_type(RunExchangeResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_exchange(self, client: Kernel) -> None:
- with client.agents.auth.runs.with_streaming_response.exchange(
- run_id="run_id",
- code="otp_abc123xyz",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = response.parse()
- assert_matches_type(RunExchangeResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_exchange(self, client: Kernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- client.agents.auth.runs.with_raw_response.exchange(
- run_id="",
- code="otp_abc123xyz",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_submit(self, client: Kernel) -> None:
- run = client.agents.auth.runs.submit(
- run_id="run_id",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- )
- assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_submit(self, client: Kernel) -> None:
- response = client.agents.auth.runs.with_raw_response.submit(
- run_id="run_id",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = response.parse()
- assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_submit(self, client: Kernel) -> None:
- with client.agents.auth.runs.with_streaming_response.submit(
- run_id="run_id",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = response.parse()
- assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_submit(self, client: Kernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- client.agents.auth.runs.with_raw_response.submit(
- run_id="",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- )
-
-
-class TestAsyncRuns:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
- run = await async_client.agents.auth.runs.retrieve(
- "run_id",
- )
- assert_matches_type(AgentAuthRunResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
- response = await async_client.agents.auth.runs.with_raw_response.retrieve(
- "run_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = await response.parse()
- assert_matches_type(AgentAuthRunResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
- async with async_client.agents.auth.runs.with_streaming_response.retrieve(
- "run_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = await response.parse()
- assert_matches_type(AgentAuthRunResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- await async_client.agents.auth.runs.with_raw_response.retrieve(
- "",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_discover(self, async_client: AsyncKernel) -> None:
- run = await async_client.agents.auth.runs.discover(
- "run_id",
- )
- assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_discover(self, async_client: AsyncKernel) -> None:
- response = await async_client.agents.auth.runs.with_raw_response.discover(
- "run_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = await response.parse()
- assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_discover(self, async_client: AsyncKernel) -> None:
- async with async_client.agents.auth.runs.with_streaming_response.discover(
- "run_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = await response.parse()
- assert_matches_type(AgentAuthDiscoverResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_discover(self, async_client: AsyncKernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- await async_client.agents.auth.runs.with_raw_response.discover(
- "",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_exchange(self, async_client: AsyncKernel) -> None:
- run = await async_client.agents.auth.runs.exchange(
- run_id="run_id",
- code="otp_abc123xyz",
- )
- assert_matches_type(RunExchangeResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_exchange(self, async_client: AsyncKernel) -> None:
- response = await async_client.agents.auth.runs.with_raw_response.exchange(
- run_id="run_id",
- code="otp_abc123xyz",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = await response.parse()
- assert_matches_type(RunExchangeResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_exchange(self, async_client: AsyncKernel) -> None:
- async with async_client.agents.auth.runs.with_streaming_response.exchange(
- run_id="run_id",
- code="otp_abc123xyz",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = await response.parse()
- assert_matches_type(RunExchangeResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_exchange(self, async_client: AsyncKernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- await async_client.agents.auth.runs.with_raw_response.exchange(
- run_id="",
- code="otp_abc123xyz",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_submit(self, async_client: AsyncKernel) -> None:
- run = await async_client.agents.auth.runs.submit(
- run_id="run_id",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- )
- assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_submit(self, async_client: AsyncKernel) -> None:
- response = await async_client.agents.auth.runs.with_raw_response.submit(
- run_id="run_id",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- run = await response.parse()
- assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_submit(self, async_client: AsyncKernel) -> None:
- async with async_client.agents.auth.runs.with_streaming_response.submit(
- run_id="run_id",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- run = await response.parse()
- assert_matches_type(AgentAuthSubmitResponse, run, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_submit(self, async_client: AsyncKernel) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- await async_client.agents.auth.runs.with_raw_response.submit(
- run_id="",
- field_values={
- "email": "user@example.com",
- "password": "********",
- },
- )
diff --git a/tests/api_resources/agents/test_auth.py b/tests/api_resources/agents/test_auth.py
deleted file mode 100644
index 32d2784f..00000000
--- a/tests/api_resources/agents/test_auth.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from kernel import Kernel, AsyncKernel
-from tests.utils import assert_matches_type
-from kernel.types.agents import AgentAuthStartResponse
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestAuth:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_start(self, client: Kernel) -> None:
- auth = client.agents.auth.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- )
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_start_with_all_params(self, client: Kernel) -> None:
- auth = client.agents.auth.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- app_logo_url="https://example.com/logo.png",
- proxy={"proxy_id": "proxy_id"},
- )
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_start(self, client: Kernel) -> None:
- response = client.agents.auth.with_raw_response.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- auth = response.parse()
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_start(self, client: Kernel) -> None:
- with client.agents.auth.with_streaming_response.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- auth = response.parse()
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncAuth:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_start(self, async_client: AsyncKernel) -> None:
- auth = await async_client.agents.auth.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- )
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_start_with_all_params(self, async_client: AsyncKernel) -> None:
- auth = await async_client.agents.auth.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- app_logo_url="https://example.com/logo.png",
- proxy={"proxy_id": "proxy_id"},
- )
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_start(self, async_client: AsyncKernel) -> None:
- response = await async_client.agents.auth.with_raw_response.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- auth = await response.parse()
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_start(self, async_client: AsyncKernel) -> None:
- async with async_client.agents.auth.with_streaming_response.start(
- profile_name="auth-abc123",
- target_domain="doordash.com",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- auth = await response.parse()
- assert_matches_type(AgentAuthStartResponse, auth, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_browser_pools.py b/tests/api_resources/test_browser_pools.py
new file mode 100644
index 00000000..6a8f164e
--- /dev/null
+++ b/tests/api_resources/test_browser_pools.py
@@ -0,0 +1,856 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from kernel import Kernel, AsyncKernel
+from tests.utils import assert_matches_type
+from kernel.types import (
+ BrowserPool,
+ BrowserPoolListResponse,
+ BrowserPoolAcquireResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestBrowserPools:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.create(
+ size=10,
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.create(
+ size=10,
+ extensions=[
+ {
+ "id": "id",
+ "name": "name",
+ }
+ ],
+ fill_rate_per_minute=0,
+ headless=False,
+ kiosk_mode=True,
+ name="my-pool",
+ profile={
+ "id": "id",
+ "name": "name",
+ "save_changes": True,
+ },
+ proxy_id="proxy_id",
+ stealth=True,
+ timeout_seconds=60,
+ viewport={
+ "height": 800,
+ "width": 1280,
+ "refresh_rate": 60,
+ },
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.create(
+ size=10,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.create(
+ size=10,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.retrieve(
+ "id_or_name",
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.retrieve(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.retrieve(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.browser_pools.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_update(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.update(
+ id_or_name="id_or_name",
+ size=10,
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.update(
+ id_or_name="id_or_name",
+ size=10,
+ discard_all_idle=False,
+ extensions=[
+ {
+ "id": "id",
+ "name": "name",
+ }
+ ],
+ fill_rate_per_minute=0,
+ headless=False,
+ kiosk_mode=True,
+ name="my-pool",
+ profile={
+ "id": "id",
+ "name": "name",
+ "save_changes": True,
+ },
+ proxy_id="proxy_id",
+ stealth=True,
+ timeout_seconds=60,
+ viewport={
+ "height": 800,
+ "width": 1280,
+ "refresh_rate": 60,
+ },
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.update(
+ id_or_name="id_or_name",
+ size=10,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.update(
+ id_or_name="id_or_name",
+ size=10,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_update(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.browser_pools.with_raw_response.update(
+ id_or_name="",
+ size=10,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.list()
+ assert_matches_type(BrowserPoolListResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPoolListResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPoolListResponse, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_delete(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.delete(
+ id_or_name="id_or_name",
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_delete_with_all_params(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.delete(
+ id_or_name="id_or_name",
+ force=True,
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.delete(
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.delete(
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert browser_pool is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_delete(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.browser_pools.with_raw_response.delete(
+ id_or_name="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_acquire(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.acquire(
+ id_or_name="id_or_name",
+ )
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_acquire_with_all_params(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.acquire(
+ id_or_name="id_or_name",
+ acquire_timeout_seconds=0,
+ )
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_acquire(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.acquire(
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_acquire(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.acquire(
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_acquire(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.browser_pools.with_raw_response.acquire(
+ id_or_name="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_flush(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.flush(
+ "id_or_name",
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_flush(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.flush(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_flush(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.flush(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert browser_pool is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_flush(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.browser_pools.with_raw_response.flush(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_release(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_release_with_all_params(self, client: Kernel) -> None:
+ browser_pool = client.browser_pools.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ reuse=False,
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_release(self, client: Kernel) -> None:
+ response = client.browser_pools.with_raw_response.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = response.parse()
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_release(self, client: Kernel) -> None:
+ with client.browser_pools.with_streaming_response.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = response.parse()
+ assert browser_pool is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_release(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.browser_pools.with_raw_response.release(
+ id_or_name="",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ )
+
+
+class TestAsyncBrowserPools:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.create(
+ size=10,
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.create(
+ size=10,
+ extensions=[
+ {
+ "id": "id",
+ "name": "name",
+ }
+ ],
+ fill_rate_per_minute=0,
+ headless=False,
+ kiosk_mode=True,
+ name="my-pool",
+ profile={
+ "id": "id",
+ "name": "name",
+ "save_changes": True,
+ },
+ proxy_id="proxy_id",
+ stealth=True,
+ timeout_seconds=60,
+ viewport={
+ "height": 800,
+ "width": 1280,
+ "refresh_rate": 60,
+ },
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.create(
+ size=10,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.create(
+ size=10,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.retrieve(
+ "id_or_name",
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.retrieve(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.retrieve(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.browser_pools.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_update(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.update(
+ id_or_name="id_or_name",
+ size=10,
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.update(
+ id_or_name="id_or_name",
+ size=10,
+ discard_all_idle=False,
+ extensions=[
+ {
+ "id": "id",
+ "name": "name",
+ }
+ ],
+ fill_rate_per_minute=0,
+ headless=False,
+ kiosk_mode=True,
+ name="my-pool",
+ profile={
+ "id": "id",
+ "name": "name",
+ "save_changes": True,
+ },
+ proxy_id="proxy_id",
+ stealth=True,
+ timeout_seconds=60,
+ viewport={
+ "height": 800,
+ "width": 1280,
+ "refresh_rate": 60,
+ },
+ )
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_update(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.update(
+ id_or_name="id_or_name",
+ size=10,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_update(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.update(
+ id_or_name="id_or_name",
+ size=10,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPool, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_update(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.browser_pools.with_raw_response.update(
+ id_or_name="",
+ size=10,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.list()
+ assert_matches_type(BrowserPoolListResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPoolListResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPoolListResponse, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.delete(
+ id_or_name="id_or_name",
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_delete_with_all_params(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.delete(
+ id_or_name="id_or_name",
+ force=True,
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.delete(
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.delete(
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert browser_pool is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_delete(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.browser_pools.with_raw_response.delete(
+ id_or_name="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_acquire(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.acquire(
+ id_or_name="id_or_name",
+ )
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_acquire_with_all_params(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.acquire(
+ id_or_name="id_or_name",
+ acquire_timeout_seconds=0,
+ )
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_acquire(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.acquire(
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_acquire(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.acquire(
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert_matches_type(BrowserPoolAcquireResponse, browser_pool, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_acquire(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.browser_pools.with_raw_response.acquire(
+ id_or_name="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_flush(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.flush(
+ "id_or_name",
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_flush(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.flush(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_flush(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.flush(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert browser_pool is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_flush(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.browser_pools.with_raw_response.flush(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_release(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_release_with_all_params(self, async_client: AsyncKernel) -> None:
+ browser_pool = await async_client.browser_pools.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ reuse=False,
+ )
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_release(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browser_pools.with_raw_response.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser_pool = await response.parse()
+ assert browser_pool is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_release(self, async_client: AsyncKernel) -> None:
+ async with async_client.browser_pools.with_streaming_response.release(
+ id_or_name="id_or_name",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser_pool = await response.parse()
+ assert browser_pool is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_release(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.browser_pools.with_raw_response.release(
+ id_or_name="",
+ session_id="ts8iy3sg25ibheguyni2lg9t",
+ )
From 77f575baaf6475b4095bf4bab530d19d9dd70a7b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 22:14:13 +0000
Subject: [PATCH 09/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index c32f96db..25e77f1e 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 74
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-340c8f009b71922347d4c238c8715cd752c8965abfa12cbb1ffabe35edc338a8.yml
-openapi_spec_hash: efc13ab03ef89cc07333db8ab5345f31
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3db06d1628149b5ea8303f1c72250664dfd7cb4a14ceb6102f1ae6e85c92c038.yml
+openapi_spec_hash: e5b3da2da328eb26d2a70e2521744c62
config_hash: a4124701ae0a474e580d7416adbcfb00
From e16538cc64d01b8ae1dd4f512fb74abb25bbbc3f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 22:14:32 +0000
Subject: [PATCH 10/10] release: 0.21.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 20 ++++++++++++++++++++
pyproject.toml | 2 +-
src/kernel/_version.py | 2 +-
4 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 0c2ecec6..86b0e83d 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.20.0"
+ ".": "0.21.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0c65e07..a726401d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# Changelog
+## 0.21.0 (2025-12-02)
+
+Full Changelog: [v0.20.0...v0.21.0](https://github.com/onkernel/kernel-python-sdk/compare/v0.20.0...v0.21.0)
+
+### Features
+
+* Browser pools sdk release ([c2d7408](https://github.com/onkernel/kernel-python-sdk/commit/c2d7408a770ddd34902986015da0bfde3477f586))
+* Mason/agent auth api ([b872928](https://github.com/onkernel/kernel-python-sdk/commit/b8729284ba804461749dad0ac4613aea3c6b3ce6))
+
+
+### Bug Fixes
+
+* ensure streams are always closed ([c82f496](https://github.com/onkernel/kernel-python-sdk/commit/c82f496ba0112b195f65da9498fb22ab65d501fb))
+
+
+### Chores
+
+* add Python 3.14 classifier and testing ([9a1e7bf](https://github.com/onkernel/kernel-python-sdk/commit/9a1e7bf9c92d64da4a151dd44cc60057c75c63bf))
+* **deps:** mypy 1.18.1 has a regression, pin to 1.17 ([038b10d](https://github.com/onkernel/kernel-python-sdk/commit/038b10d52935961c37ebb0806e9b0754b4d53a20))
+
## 0.20.0 (2025-11-19)
Full Changelog: [v0.19.2...v0.20.0](https://github.com/onkernel/kernel-python-sdk/compare/v0.19.2...v0.20.0)
diff --git a/pyproject.toml b/pyproject.toml
index 71c4c9aa..f4bbe655 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "kernel"
-version = "0.20.0"
+version = "0.21.0"
description = "The official Python library for the kernel API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/kernel/_version.py b/src/kernel/_version.py
index 1a28cba2..1bd01d63 100644
--- a/src/kernel/_version.py
+++ b/src/kernel/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "kernel"
-__version__ = "0.20.0" # x-release-please-version
+__version__ = "0.21.0" # x-release-please-version