From 83e4f2c26f02a7df56917e993af1e1d85ba241e6 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Jun 2025 02:10:30 +0000
Subject: [PATCH 01/23] chore(tests): run tests in parallel
---
pyproject.toml | 3 ++-
requirements-dev.lock | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 4c9fc23..ce8b48d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -54,6 +54,7 @@ dev-dependencies = [
"importlib-metadata>=6.7.0",
"rich>=13.7.1",
"nest_asyncio==1.6.0",
+ "pytest-xdist>=3.6.1",
]
[tool.rye.scripts]
@@ -125,7 +126,7 @@ replacement = '[\1](https://github.com/onkernel/kernel-python-sdk/tree/main/\g<2
[tool.pytest.ini_options]
testpaths = ["tests"]
-addopts = "--tb=short"
+addopts = "--tb=short -n auto"
xfail_strict = true
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
diff --git a/requirements-dev.lock b/requirements-dev.lock
index efd90ea..f40d985 100644
--- a/requirements-dev.lock
+++ b/requirements-dev.lock
@@ -30,6 +30,8 @@ distro==1.8.0
exceptiongroup==1.2.2
# via anyio
# via pytest
+execnet==2.1.1
+ # via pytest-xdist
filelock==3.12.4
# via virtualenv
h11==0.14.0
@@ -72,7 +74,9 @@ pygments==2.18.0
pyright==1.1.399
pytest==8.3.3
# via pytest-asyncio
+ # via pytest-xdist
pytest-asyncio==0.24.0
+pytest-xdist==3.7.0
python-dateutil==2.8.2
# via time-machine
pytz==2023.3.post1
From 007934910a1ec8e17a6be821feacef9b42a2c142 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Jun 2025 02:35:04 +0000
Subject: [PATCH 02/23] fix(client): correctly parse binary response | stream
---
src/kernel/_base_client.py | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/kernel/_base_client.py b/src/kernel/_base_client.py
index 785adea..c86e919 100644
--- a/src/kernel/_base_client.py
+++ b/src/kernel/_base_client.py
@@ -1071,7 +1071,14 @@ def _process_response(
) -> ResponseT:
origin = get_origin(cast_to) or cast_to
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
+ if (
+ inspect.isclass(origin)
+ and issubclass(origin, BaseAPIResponse)
+ # we only want to actually return the custom BaseAPIResponse class if we're
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
+ ):
if not issubclass(origin, APIResponse):
raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}")
@@ -1574,7 +1581,14 @@ async def _process_response(
) -> ResponseT:
origin = get_origin(cast_to) or cast_to
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
+ if (
+ inspect.isclass(origin)
+ and issubclass(origin, BaseAPIResponse)
+ # we only want to actually return the custom BaseAPIResponse class if we're
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
+ ):
if not issubclass(origin, AsyncAPIResponse):
raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
From 7bd810a49eb26d4a62e924b25e52c22ec3e5dfde Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 19:42:26 +0000
Subject: [PATCH 03/23] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index d654666..d2422bd 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 11
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4502c65bef0843a6ae96d23bba075433af6bab49b55b544b1522f63e7881c00c.yml
-openapi_spec_hash: 3e67b77bbc8cd6155b8f66f3271f2643
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fa302aa17477431aaa82682fe71bdbb519270815fdc917477e1d7e606411be50.yml
+openapi_spec_hash: 291cb0245ba582712900f0fb5cf44ee4
config_hash: c6bab7ac8da570a5abbcfb19db119b6b
From 2e69f9952537d5fb4fc4ea7502a567c07ff3c6ab Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 19:47:29 +0000
Subject: [PATCH 04/23] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index d2422bd..8826a54 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 11
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fa302aa17477431aaa82682fe71bdbb519270815fdc917477e1d7e606411be50.yml
-openapi_spec_hash: 291cb0245ba582712900f0fb5cf44ee4
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e622f6886b1153050eb4ee9fda37fff8b36b38b52e5d247ea172deb2594bf9d6.yml
+openapi_spec_hash: 3fa294f57c68b34e526a52bdd86eb562
config_hash: c6bab7ac8da570a5abbcfb19db119b6b
From 496e5cd31745446c16234120f9299be4a9830bb5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 19:59:19 +0000
Subject: [PATCH 05/23] feat(api): update via SDK Studio
---
.stats.yml | 8 +-
api.md | 18 +
src/kernel/_client.py | 10 +-
src/kernel/resources/__init__.py | 14 +
src/kernel/resources/deployments.py | 407 ++++++++++++++++++
src/kernel/types/__init__.py | 4 +
src/kernel/types/deployment_create_params.py | 33 ++
.../types/deployment_create_response.py | 35 ++
.../types/deployment_follow_response.py | 129 ++++++
.../types/deployment_retrieve_response.py | 35 ++
tests/api_resources/test_deployments.py | 304 +++++++++++++
11 files changed, 992 insertions(+), 5 deletions(-)
create mode 100644 src/kernel/resources/deployments.py
create mode 100644 src/kernel/types/deployment_create_params.py
create mode 100644 src/kernel/types/deployment_create_response.py
create mode 100644 src/kernel/types/deployment_follow_response.py
create mode 100644 src/kernel/types/deployment_retrieve_response.py
create mode 100644 tests/api_resources/test_deployments.py
diff --git a/.stats.yml b/.stats.yml
index 8826a54..f34bfc3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 11
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e622f6886b1153050eb4ee9fda37fff8b36b38b52e5d247ea172deb2594bf9d6.yml
-openapi_spec_hash: 3fa294f57c68b34e526a52bdd86eb562
-config_hash: c6bab7ac8da570a5abbcfb19db119b6b
+configured_endpoints: 14
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d2dfee8d576aa73f6075e6da61228571cb2e844b969a06067e34e43eb7898554.yml
+openapi_spec_hash: 9981744bf9c27426cdf721f7b27cf093
+config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/api.md b/api.md
index cbacba5..db76da3 100644
--- a/api.md
+++ b/api.md
@@ -1,3 +1,21 @@
+# Deployments
+
+Types:
+
+```python
+from kernel.types import (
+ DeploymentCreateResponse,
+ DeploymentRetrieveResponse,
+ DeploymentFollowResponse,
+)
+```
+
+Methods:
+
+- client.deployments.create(\*\*params) -> DeploymentCreateResponse
+- client.deployments.retrieve(id) -> DeploymentRetrieveResponse
+- client.deployments.follow(id) -> DeploymentFollowResponse
+
# Apps
Types:
diff --git a/src/kernel/_client.py b/src/kernel/_client.py
index bf6fbb4..084d2a5 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 browsers
+from .resources import browsers, deployments
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import KernelError, APIStatusError
from ._base_client import (
@@ -50,6 +50,7 @@
class Kernel(SyncAPIClient):
+ deployments: deployments.DeploymentsResource
apps: apps.AppsResource
browsers: browsers.BrowsersResource
with_raw_response: KernelWithRawResponse
@@ -133,6 +134,7 @@ def __init__(
_strict_response_validation=_strict_response_validation,
)
+ self.deployments = deployments.DeploymentsResource(self)
self.apps = apps.AppsResource(self)
self.browsers = browsers.BrowsersResource(self)
self.with_raw_response = KernelWithRawResponse(self)
@@ -246,6 +248,7 @@ def _make_status_error(
class AsyncKernel(AsyncAPIClient):
+ deployments: deployments.AsyncDeploymentsResource
apps: apps.AsyncAppsResource
browsers: browsers.AsyncBrowsersResource
with_raw_response: AsyncKernelWithRawResponse
@@ -329,6 +332,7 @@ def __init__(
_strict_response_validation=_strict_response_validation,
)
+ self.deployments = deployments.AsyncDeploymentsResource(self)
self.apps = apps.AsyncAppsResource(self)
self.browsers = browsers.AsyncBrowsersResource(self)
self.with_raw_response = AsyncKernelWithRawResponse(self)
@@ -443,24 +447,28 @@ def _make_status_error(
class KernelWithRawResponse:
def __init__(self, client: Kernel) -> None:
+ self.deployments = deployments.DeploymentsResourceWithRawResponse(client.deployments)
self.apps = apps.AppsResourceWithRawResponse(client.apps)
self.browsers = browsers.BrowsersResourceWithRawResponse(client.browsers)
class AsyncKernelWithRawResponse:
def __init__(self, client: AsyncKernel) -> None:
+ self.deployments = deployments.AsyncDeploymentsResourceWithRawResponse(client.deployments)
self.apps = apps.AsyncAppsResourceWithRawResponse(client.apps)
self.browsers = browsers.AsyncBrowsersResourceWithRawResponse(client.browsers)
class KernelWithStreamedResponse:
def __init__(self, client: Kernel) -> None:
+ self.deployments = deployments.DeploymentsResourceWithStreamingResponse(client.deployments)
self.apps = apps.AppsResourceWithStreamingResponse(client.apps)
self.browsers = browsers.BrowsersResourceWithStreamingResponse(client.browsers)
class AsyncKernelWithStreamedResponse:
def __init__(self, client: AsyncKernel) -> None:
+ self.deployments = deployments.AsyncDeploymentsResourceWithStreamingResponse(client.deployments)
self.apps = apps.AsyncAppsResourceWithStreamingResponse(client.apps)
self.browsers = browsers.AsyncBrowsersResourceWithStreamingResponse(client.browsers)
diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py
index 647bde6..f65d1db 100644
--- a/src/kernel/resources/__init__.py
+++ b/src/kernel/resources/__init__.py
@@ -16,8 +16,22 @@
BrowsersResourceWithStreamingResponse,
AsyncBrowsersResourceWithStreamingResponse,
)
+from .deployments import (
+ DeploymentsResource,
+ AsyncDeploymentsResource,
+ DeploymentsResourceWithRawResponse,
+ AsyncDeploymentsResourceWithRawResponse,
+ DeploymentsResourceWithStreamingResponse,
+ AsyncDeploymentsResourceWithStreamingResponse,
+)
__all__ = [
+ "DeploymentsResource",
+ "AsyncDeploymentsResource",
+ "DeploymentsResourceWithRawResponse",
+ "AsyncDeploymentsResourceWithRawResponse",
+ "DeploymentsResourceWithStreamingResponse",
+ "AsyncDeploymentsResourceWithStreamingResponse",
"AppsResource",
"AsyncAppsResource",
"AppsResourceWithRawResponse",
diff --git a/src/kernel/resources/deployments.py b/src/kernel/resources/deployments.py
new file mode 100644
index 0000000..6442ff0
--- /dev/null
+++ b/src/kernel/resources/deployments.py
@@ -0,0 +1,407 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Any, Dict, Mapping, cast
+from typing_extensions import Literal
+
+import httpx
+
+from ..types import deployment_create_params
+from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, 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 .._streaming import Stream, AsyncStream
+from .._base_client import make_request_options
+from ..types.deployment_create_response import DeploymentCreateResponse
+from ..types.deployment_follow_response import DeploymentFollowResponse
+from ..types.deployment_retrieve_response import DeploymentRetrieveResponse
+
+__all__ = ["DeploymentsResource", "AsyncDeploymentsResource"]
+
+
+class DeploymentsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> DeploymentsResourceWithRawResponse:
+ """
+ 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 DeploymentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> DeploymentsResourceWithStreamingResponse:
+ """
+ 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 DeploymentsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ entrypoint_rel_path: str,
+ file: FileTypes,
+ env_vars: Dict[str, str] | NotGiven = NOT_GIVEN,
+ force: bool | NotGiven = NOT_GIVEN,
+ region: Literal["aws.us-east-1a"] | NotGiven = NOT_GIVEN,
+ version: str | NotGiven = NOT_GIVEN,
+ # 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,
+ ) -> DeploymentCreateResponse:
+ """
+ Create a new deployment.
+
+ Args:
+ entrypoint_rel_path: Relative path to the entrypoint of the application
+
+ file: ZIP file containing the application source directory
+
+ env_vars: Map of environment variables to set for the deployed application. Each key-value
+ pair represents an environment variable.
+
+ force: Allow overwriting an existing app version
+
+ region: Region for deployment. Currently we only support "aws.us-east-1a"
+
+ version: Version of the application. Can be any string.
+
+ 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
+ """
+ body = deepcopy_minimal(
+ {
+ "entrypoint_rel_path": entrypoint_rel_path,
+ "file": file,
+ "env_vars": env_vars,
+ "force": force,
+ "region": region,
+ "version": version,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/deployments",
+ body=maybe_transform(body, deployment_create_params.DeploymentCreateParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DeploymentCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ 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,
+ ) -> DeploymentRetrieveResponse:
+ """
+ Get information about a deployment's status.
+
+ 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:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._get(
+ f"/deployments/{id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DeploymentRetrieveResponse,
+ )
+
+ def follow(
+ self,
+ 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,
+ ) -> Stream[DeploymentFollowResponse]:
+ """
+ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and
+ status updates for a deployment. The stream terminates automatically once the
+ deployment reaches a terminal state.
+
+ 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:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ return self._get(
+ f"/deployments/{id}/events",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(
+ Any, DeploymentFollowResponse
+ ), # Union types cannot be passed in as arguments in the type system
+ stream=True,
+ stream_cls=Stream[DeploymentFollowResponse],
+ )
+
+
+class AsyncDeploymentsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncDeploymentsResourceWithRawResponse:
+ """
+ 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 AsyncDeploymentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncDeploymentsResourceWithStreamingResponse:
+ """
+ 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 AsyncDeploymentsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ entrypoint_rel_path: str,
+ file: FileTypes,
+ env_vars: Dict[str, str] | NotGiven = NOT_GIVEN,
+ force: bool | NotGiven = NOT_GIVEN,
+ region: Literal["aws.us-east-1a"] | NotGiven = NOT_GIVEN,
+ version: str | NotGiven = NOT_GIVEN,
+ # 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,
+ ) -> DeploymentCreateResponse:
+ """
+ Create a new deployment.
+
+ Args:
+ entrypoint_rel_path: Relative path to the entrypoint of the application
+
+ file: ZIP file containing the application source directory
+
+ env_vars: Map of environment variables to set for the deployed application. Each key-value
+ pair represents an environment variable.
+
+ force: Allow overwriting an existing app version
+
+ region: Region for deployment. Currently we only support "aws.us-east-1a"
+
+ version: Version of the application. Can be any string.
+
+ 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
+ """
+ body = deepcopy_minimal(
+ {
+ "entrypoint_rel_path": entrypoint_rel_path,
+ "file": file,
+ "env_vars": env_vars,
+ "force": force,
+ "region": region,
+ "version": version,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/deployments",
+ body=await async_maybe_transform(body, deployment_create_params.DeploymentCreateParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DeploymentCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ 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,
+ ) -> DeploymentRetrieveResponse:
+ """
+ Get information about a deployment's status.
+
+ 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:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._get(
+ f"/deployments/{id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DeploymentRetrieveResponse,
+ )
+
+ async def follow(
+ self,
+ 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,
+ ) -> AsyncStream[DeploymentFollowResponse]:
+ """
+ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and
+ status updates for a deployment. The stream terminates automatically once the
+ deployment reaches a terminal state.
+
+ 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:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ return await self._get(
+ f"/deployments/{id}/events",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(
+ Any, DeploymentFollowResponse
+ ), # Union types cannot be passed in as arguments in the type system
+ stream=True,
+ stream_cls=AsyncStream[DeploymentFollowResponse],
+ )
+
+
+class DeploymentsResourceWithRawResponse:
+ def __init__(self, deployments: DeploymentsResource) -> None:
+ self._deployments = deployments
+
+ self.create = to_raw_response_wrapper(
+ deployments.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ deployments.retrieve,
+ )
+ self.follow = to_raw_response_wrapper(
+ deployments.follow,
+ )
+
+
+class AsyncDeploymentsResourceWithRawResponse:
+ def __init__(self, deployments: AsyncDeploymentsResource) -> None:
+ self._deployments = deployments
+
+ self.create = async_to_raw_response_wrapper(
+ deployments.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ deployments.retrieve,
+ )
+ self.follow = async_to_raw_response_wrapper(
+ deployments.follow,
+ )
+
+
+class DeploymentsResourceWithStreamingResponse:
+ def __init__(self, deployments: DeploymentsResource) -> None:
+ self._deployments = deployments
+
+ self.create = to_streamed_response_wrapper(
+ deployments.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ deployments.retrieve,
+ )
+ self.follow = to_streamed_response_wrapper(
+ deployments.follow,
+ )
+
+
+class AsyncDeploymentsResourceWithStreamingResponse:
+ def __init__(self, deployments: AsyncDeploymentsResource) -> None:
+ self._deployments = deployments
+
+ self.create = async_to_streamed_response_wrapper(
+ deployments.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ deployments.retrieve,
+ )
+ self.follow = async_to_streamed_response_wrapper(
+ deployments.follow,
+ )
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index d6ca955..93a1ee8 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -9,5 +9,9 @@
from .browser_delete_params import BrowserDeleteParams as BrowserDeleteParams
from .browser_list_response import BrowserListResponse as BrowserListResponse
from .browser_create_response import BrowserCreateResponse as BrowserCreateResponse
+from .deployment_create_params import DeploymentCreateParams as DeploymentCreateParams
from .browser_persistence_param import BrowserPersistenceParam as BrowserPersistenceParam
from .browser_retrieve_response import BrowserRetrieveResponse as BrowserRetrieveResponse
+from .deployment_create_response import DeploymentCreateResponse as DeploymentCreateResponse
+from .deployment_follow_response import DeploymentFollowResponse as DeploymentFollowResponse
+from .deployment_retrieve_response import DeploymentRetrieveResponse as DeploymentRetrieveResponse
diff --git a/src/kernel/types/deployment_create_params.py b/src/kernel/types/deployment_create_params.py
new file mode 100644
index 0000000..6701c0a
--- /dev/null
+++ b/src/kernel/types/deployment_create_params.py
@@ -0,0 +1,33 @@
+# 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 Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["DeploymentCreateParams"]
+
+
+class DeploymentCreateParams(TypedDict, total=False):
+ entrypoint_rel_path: Required[str]
+ """Relative path to the entrypoint of the application"""
+
+ file: Required[FileTypes]
+ """ZIP file containing the application source directory"""
+
+ env_vars: Dict[str, str]
+ """Map of environment variables to set for the deployed application.
+
+ Each key-value pair represents an environment variable.
+ """
+
+ force: bool
+ """Allow overwriting an existing app version"""
+
+ region: Literal["aws.us-east-1a"]
+ """Region for deployment. Currently we only support "aws.us-east-1a" """
+
+ version: str
+ """Version of the application. Can be any string."""
diff --git a/src/kernel/types/deployment_create_response.py b/src/kernel/types/deployment_create_response.py
new file mode 100644
index 0000000..0f5d2b2
--- /dev/null
+++ b/src/kernel/types/deployment_create_response.py
@@ -0,0 +1,35 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["DeploymentCreateResponse"]
+
+
+class DeploymentCreateResponse(BaseModel):
+ id: str
+ """Unique identifier for the deployment"""
+
+ created_at: datetime
+ """Timestamp when the deployment was created"""
+
+ region: str
+ """Deployment region code"""
+
+ status: Literal["queued", "in_progress", "running", "failed", "stopped"]
+ """Current status of the deployment"""
+
+ entrypoint_rel_path: Optional[str] = None
+ """Relative path to the application entrypoint"""
+
+ env_vars: Optional[Dict[str, str]] = None
+ """Environment variables configured for this deployment"""
+
+ status_reason: Optional[str] = None
+ """Status reason"""
+
+ updated_at: Optional[datetime] = None
+ """Timestamp when the deployment was last updated"""
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
new file mode 100644
index 0000000..09f1abc
--- /dev/null
+++ b/src/kernel/types/deployment_follow_response.py
@@ -0,0 +1,129 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+
+__all__ = [
+ "DeploymentFollowResponse",
+ "LogEvent",
+ "DeploymentStateEvent",
+ "DeploymentStateEventDeployment",
+ "AppVersionSummaryEvent",
+ "ErrorEvent",
+ "ErrorEventError",
+ "ErrorEventErrorDetail",
+ "ErrorEventErrorInnerError",
+]
+
+
+class LogEvent(BaseModel):
+ event: Literal["log"]
+ """Event type identifier (always "log")."""
+
+ message: str
+ """Log message text."""
+
+ timestamp: Optional[datetime] = None
+ """Time the log entry was produced."""
+
+
+class DeploymentStateEventDeployment(BaseModel):
+ id: str
+ """Unique identifier for the deployment"""
+
+ created_at: datetime
+ """Timestamp when the deployment was created"""
+
+ region: str
+ """Deployment region code"""
+
+ status: Literal["queued", "in_progress", "running", "failed", "stopped"]
+ """Current status of the deployment"""
+
+ entrypoint_rel_path: Optional[str] = None
+ """Relative path to the application entrypoint"""
+
+ env_vars: Optional[Dict[str, str]] = None
+ """Environment variables configured for this deployment"""
+
+ status_reason: Optional[str] = None
+ """Status reason"""
+
+ updated_at: Optional[datetime] = None
+ """Timestamp when the deployment was last updated"""
+
+
+class DeploymentStateEvent(BaseModel):
+ deployment: DeploymentStateEventDeployment
+ """Deployment record information."""
+
+ event: Literal["deployment_state"]
+ """Event type identifier (always "deployment_state")."""
+
+ timestamp: Optional[datetime] = None
+ """Time the state was reported."""
+
+
+class AppVersionSummaryEvent(BaseModel):
+ id: Optional[str] = None
+ """Unique identifier for the app version"""
+
+ app_name: Optional[str] = None
+ """Name of the application"""
+
+ env_vars: Optional[Dict[str, str]] = None
+ """Environment variables configured for this app version"""
+
+ event: Optional[Literal["app_version_summary"]] = None
+ """Event type identifier (always "app_version_summary")."""
+
+ region: Optional[str] = None
+ """Deployment region code"""
+
+ version: Optional[str] = None
+ """Version label for the application"""
+
+
+class ErrorEventErrorDetail(BaseModel):
+ code: Optional[str] = None
+ """Lower-level error code providing more specific detail"""
+
+ message: Optional[str] = None
+ """Further detail about the error"""
+
+
+class ErrorEventErrorInnerError(BaseModel):
+ code: Optional[str] = None
+ """Lower-level error code providing more specific detail"""
+
+ message: Optional[str] = None
+ """Further detail about the error"""
+
+
+class ErrorEventError(BaseModel):
+ code: str
+ """Application-specific error code (machine-readable)"""
+
+ message: str
+ """Human-readable error description for debugging"""
+
+ details: Optional[List[ErrorEventErrorDetail]] = None
+ """Additional error details (for multiple errors)"""
+
+ inner_error: Optional[ErrorEventErrorInnerError] = None
+
+
+class ErrorEvent(BaseModel):
+ error: Optional[ErrorEventError] = None
+
+ event: Optional[Literal["error"]] = None
+ """Event type identifier (always "error")."""
+
+
+DeploymentFollowResponse: TypeAlias = Annotated[
+ Union[LogEvent, DeploymentStateEvent, AppVersionSummaryEvent, ErrorEvent], PropertyInfo(discriminator="event")
+]
diff --git a/src/kernel/types/deployment_retrieve_response.py b/src/kernel/types/deployment_retrieve_response.py
new file mode 100644
index 0000000..efe9f7b
--- /dev/null
+++ b/src/kernel/types/deployment_retrieve_response.py
@@ -0,0 +1,35 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["DeploymentRetrieveResponse"]
+
+
+class DeploymentRetrieveResponse(BaseModel):
+ id: str
+ """Unique identifier for the deployment"""
+
+ created_at: datetime
+ """Timestamp when the deployment was created"""
+
+ region: str
+ """Deployment region code"""
+
+ status: Literal["queued", "in_progress", "running", "failed", "stopped"]
+ """Current status of the deployment"""
+
+ entrypoint_rel_path: Optional[str] = None
+ """Relative path to the application entrypoint"""
+
+ env_vars: Optional[Dict[str, str]] = None
+ """Environment variables configured for this deployment"""
+
+ status_reason: Optional[str] = None
+ """Status reason"""
+
+ updated_at: Optional[datetime] = None
+ """Timestamp when the deployment was last updated"""
diff --git a/tests/api_resources/test_deployments.py b/tests/api_resources/test_deployments.py
new file mode 100644
index 0000000..4bd80fc
--- /dev/null
+++ b/tests/api_resources/test_deployments.py
@@ -0,0 +1,304 @@
+# 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 DeploymentCreateResponse, DeploymentRetrieveResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestDeployments:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_create(self, client: Kernel) -> None:
+ deployment = client.deployments.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ )
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_create_with_all_params(self, client: Kernel) -> None:
+ deployment = client.deployments.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ env_vars={"foo": "string"},
+ force=False,
+ region="aws.us-east-1a",
+ version="1.0.0",
+ )
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_raw_response_create(self, client: Kernel) -> None:
+ response = client.deployments.with_raw_response.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ deployment = response.parse()
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_streaming_response_create(self, client: Kernel) -> None:
+ with client.deployments.with_streaming_response.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ deployment = response.parse()
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_retrieve(self, client: Kernel) -> None:
+ deployment = client.deployments.retrieve(
+ "id",
+ )
+ assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_raw_response_retrieve(self, client: Kernel) -> None:
+ response = client.deployments.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ deployment = response.parse()
+ assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Kernel) -> None:
+ with client.deployments.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ deployment = response.parse()
+ assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_path_params_retrieve(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.deployments.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_method_follow(self, client: Kernel) -> None:
+ deployment_stream = client.deployments.follow(
+ "id",
+ )
+ deployment_stream.response.close()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_raw_response_follow(self, client: Kernel) -> None:
+ response = client.deployments.with_raw_response.follow(
+ "id",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = response.parse()
+ stream.close()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_streaming_response_follow(self, client: Kernel) -> None:
+ with client.deployments.with_streaming_response.follow(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = response.parse()
+ stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_path_params_follow(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.deployments.with_raw_response.follow(
+ "",
+ )
+
+
+class TestAsyncDeployments:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_create(self, async_client: AsyncKernel) -> None:
+ deployment = await async_client.deployments.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ )
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> None:
+ deployment = await async_client.deployments.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ env_vars={"foo": "string"},
+ force=False,
+ region="aws.us-east-1a",
+ version="1.0.0",
+ )
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncKernel) -> None:
+ response = await async_client.deployments.with_raw_response.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ deployment = await response.parse()
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncKernel) -> None:
+ async with async_client.deployments.with_streaming_response.create(
+ entrypoint_rel_path="src/app.py",
+ file=b"raw file contents",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ deployment = await response.parse()
+ assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
+ deployment = await async_client.deployments.retrieve(
+ "id",
+ )
+ assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
+ response = await async_client.deployments.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ deployment = await response.parse()
+ assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
+ async with async_client.deployments.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ deployment = await response.parse()
+ assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @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` but received ''"):
+ await async_client.deployments.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_method_follow(self, async_client: AsyncKernel) -> None:
+ deployment_stream = await async_client.deployments.follow(
+ "id",
+ )
+ await deployment_stream.response.aclose()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_raw_response_follow(self, async_client: AsyncKernel) -> None:
+ response = await async_client.deployments.with_raw_response.follow(
+ "id",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = await response.parse()
+ await stream.close()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_streaming_response_follow(self, async_client: AsyncKernel) -> None:
+ async with async_client.deployments.with_streaming_response.follow(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = await response.parse()
+ await stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_path_params_follow(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.deployments.with_raw_response.follow(
+ "",
+ )
From 452e83c41d808b97e1ff54cdfa79d74abccfc9b5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 20:04:00 +0000
Subject: [PATCH 06/23] feat(api): update via SDK Studio
---
.stats.yml | 4 +--
.../types/apps/deployment_follow_response.py | 2 +-
.../types/deployment_follow_response.py | 30 +++++++++++--------
3 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index f34bfc3..f219d4b 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d2dfee8d576aa73f6075e6da61228571cb2e844b969a06067e34e43eb7898554.yml
-openapi_spec_hash: 9981744bf9c27426cdf721f7b27cf093
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aec3b879aa30638614c6217afbafcf737f37ac78ef3a51186dbf7b6fbf9e91ef.yml
+openapi_spec_hash: 0aba27c707612e35b4068b1d748dc379
config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/src/kernel/types/apps/deployment_follow_response.py b/src/kernel/types/apps/deployment_follow_response.py
index eb1ded7..cee006c 100644
--- a/src/kernel/types/apps/deployment_follow_response.py
+++ b/src/kernel/types/apps/deployment_follow_response.py
@@ -41,7 +41,7 @@ class LogEvent(BaseModel):
message: str
"""Log message text."""
- timestamp: Optional[datetime] = None
+ timestamp: datetime
"""Time the log entry was produced."""
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 09f1abc..59830fa 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -27,7 +27,7 @@ class LogEvent(BaseModel):
message: str
"""Log message text."""
- timestamp: Optional[datetime] = None
+ timestamp: datetime
"""Time the log entry was produced."""
@@ -64,29 +64,32 @@ class DeploymentStateEvent(BaseModel):
event: Literal["deployment_state"]
"""Event type identifier (always "deployment_state")."""
- timestamp: Optional[datetime] = None
+ timestamp: datetime
"""Time the state was reported."""
class AppVersionSummaryEvent(BaseModel):
- id: Optional[str] = None
+ id: str
"""Unique identifier for the app version"""
- app_name: Optional[str] = None
+ app_name: str
"""Name of the application"""
- env_vars: Optional[Dict[str, str]] = None
- """Environment variables configured for this app version"""
-
- event: Optional[Literal["app_version_summary"]] = None
+ event: Literal["app_version_summary"]
"""Event type identifier (always "app_version_summary")."""
- region: Optional[str] = None
+ region: str
"""Deployment region code"""
- version: Optional[str] = None
+ timestamp: datetime
+ """Time the state was reported."""
+
+ version: str
"""Version label for the application"""
+ env_vars: Optional[Dict[str, str]] = None
+ """Environment variables configured for this app version"""
+
class ErrorEventErrorDetail(BaseModel):
code: Optional[str] = None
@@ -118,11 +121,14 @@ class ErrorEventError(BaseModel):
class ErrorEvent(BaseModel):
- error: Optional[ErrorEventError] = None
+ error: ErrorEventError
- event: Optional[Literal["error"]] = None
+ event: Literal["error"]
"""Event type identifier (always "error")."""
+ timestamp: datetime
+ """Time the error occurred."""
+
DeploymentFollowResponse: TypeAlias = Annotated[
Union[LogEvent, DeploymentStateEvent, AppVersionSummaryEvent, ErrorEvent], PropertyInfo(discriminator="event")
From d51332b18af547affb215d9a7596bbbdb7ccff24 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 21:04:27 +0000
Subject: [PATCH 07/23] feat(api): update via SDK Studio
---
.stats.yml | 4 ++--
src/kernel/types/deployment_follow_response.py | 3 +++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index f219d4b..c68e415 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aec3b879aa30638614c6217afbafcf737f37ac78ef3a51186dbf7b6fbf9e91ef.yml
-openapi_spec_hash: 0aba27c707612e35b4068b1d748dc379
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aac74422364f9d25e30fcefd510297580b77be4b84c71416c5b9de5b882e5945.yml
+openapi_spec_hash: 4d42a5d93bd82754acf11e32e7438a04
config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 59830fa..60860c1 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -87,6 +87,9 @@ class AppVersionSummaryEvent(BaseModel):
version: str
"""Version label for the application"""
+ actions: Optional[List[str]] = None
+ """List of actions available on the app"""
+
env_vars: Optional[Dict[str, str]] = None
"""Environment variables configured for this app version"""
From 76991114e757c0c054e89d614619e38b2ec7d918 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 22:37:33 +0000
Subject: [PATCH 08/23] feat(api): update via SDK Studio
---
.stats.yml | 4 ++--
src/kernel/types/app_list_response.py | 4 ++--
src/kernel/types/deployment_create_response.py | 2 +-
src/kernel/types/deployment_follow_response.py | 4 ++--
src/kernel/types/deployment_retrieve_response.py | 2 +-
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index c68e415..3f66d22 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aac74422364f9d25e30fcefd510297580b77be4b84c71416c5b9de5b882e5945.yml
-openapi_spec_hash: 4d42a5d93bd82754acf11e32e7438a04
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2fed6c2aef6fb20a2815d0ed36d801c566a73ea11a66db5d892b1533a1fac19e.yml
+openapi_spec_hash: 55559a2ca985ed36cb8a13b09f80dcb5
config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/src/kernel/types/app_list_response.py b/src/kernel/types/app_list_response.py
index 8a6f621..1d35fd2 100644
--- a/src/kernel/types/app_list_response.py
+++ b/src/kernel/types/app_list_response.py
@@ -1,7 +1,7 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Dict, List, Optional
-from typing_extensions import TypeAlias
+from typing_extensions import Literal, TypeAlias
from .._models import BaseModel
@@ -15,7 +15,7 @@ class AppListResponseItem(BaseModel):
app_name: str
"""Name of the application"""
- region: str
+ region: Literal["aws.us-east-1a"]
"""Deployment region code"""
version: str
diff --git a/src/kernel/types/deployment_create_response.py b/src/kernel/types/deployment_create_response.py
index 0f5d2b2..c14bf27 100644
--- a/src/kernel/types/deployment_create_response.py
+++ b/src/kernel/types/deployment_create_response.py
@@ -16,7 +16,7 @@ class DeploymentCreateResponse(BaseModel):
created_at: datetime
"""Timestamp when the deployment was created"""
- region: str
+ region: Literal["aws.us-east-1a"]
"""Deployment region code"""
status: Literal["queued", "in_progress", "running", "failed", "stopped"]
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 60860c1..bcc98a0 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -38,7 +38,7 @@ class DeploymentStateEventDeployment(BaseModel):
created_at: datetime
"""Timestamp when the deployment was created"""
- region: str
+ region: Literal["aws.us-east-1a"]
"""Deployment region code"""
status: Literal["queued", "in_progress", "running", "failed", "stopped"]
@@ -78,7 +78,7 @@ class AppVersionSummaryEvent(BaseModel):
event: Literal["app_version_summary"]
"""Event type identifier (always "app_version_summary")."""
- region: str
+ region: Literal["aws.us-east-1a"]
"""Deployment region code"""
timestamp: datetime
diff --git a/src/kernel/types/deployment_retrieve_response.py b/src/kernel/types/deployment_retrieve_response.py
index efe9f7b..28c0d4b 100644
--- a/src/kernel/types/deployment_retrieve_response.py
+++ b/src/kernel/types/deployment_retrieve_response.py
@@ -16,7 +16,7 @@ class DeploymentRetrieveResponse(BaseModel):
created_at: datetime
"""Timestamp when the deployment was created"""
- region: str
+ region: Literal["aws.us-east-1a"]
"""Deployment region code"""
status: Literal["queued", "in_progress", "running", "failed", "stopped"]
From eed8e6769fd4982cadb277aa4c271c211992077a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 23:01:10 +0000
Subject: [PATCH 09/23] feat(api): update via SDK Studio
---
.stats.yml | 4 ++--
src/kernel/types/deployment_follow_response.py | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 3f66d22..4dea91f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2fed6c2aef6fb20a2815d0ed36d801c566a73ea11a66db5d892b1533a1fac19e.yml
-openapi_spec_hash: 55559a2ca985ed36cb8a13b09f80dcb5
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-da3b6999bce525461011a620a559d34d4b4ab1d073758e7add4d2ba09f57a2ba.yml
+openapi_spec_hash: 7bec5f31fa27666a3955076653c6ac40
config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index bcc98a0..757b51a 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -72,6 +72,9 @@ class AppVersionSummaryEvent(BaseModel):
id: str
"""Unique identifier for the app version"""
+ actions: List[str]
+ """List of actions available on the app"""
+
app_name: str
"""Name of the application"""
@@ -87,9 +90,6 @@ class AppVersionSummaryEvent(BaseModel):
version: str
"""Version label for the application"""
- actions: Optional[List[str]] = None
- """List of actions available on the app"""
-
env_vars: Optional[Dict[str, str]] = None
"""Environment variables configured for this app version"""
From c1cdbcc6e555ab5fc7ecc229095ff7d0bf272e1a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 23:12:42 +0000
Subject: [PATCH 10/23] feat(api): update via SDK Studio
---
.stats.yml | 4 ++--
src/kernel/types/deployment_follow_response.py | 8 +++++++-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 4dea91f..3ea11ab 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-da3b6999bce525461011a620a559d34d4b4ab1d073758e7add4d2ba09f57a2ba.yml
-openapi_spec_hash: 7bec5f31fa27666a3955076653c6ac40
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b8c3224543bfd828075063a87302ec205b54f8b24658cc869b98aa81d995d855.yml
+openapi_spec_hash: 52f5b821303fef54e61bae285f185200
config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 757b51a..44a17a6 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -13,6 +13,7 @@
"DeploymentStateEvent",
"DeploymentStateEventDeployment",
"AppVersionSummaryEvent",
+ "AppVersionSummaryEventAction",
"ErrorEvent",
"ErrorEventError",
"ErrorEventErrorDetail",
@@ -68,11 +69,16 @@ class DeploymentStateEvent(BaseModel):
"""Time the state was reported."""
+class AppVersionSummaryEventAction(BaseModel):
+ name: str
+ """Name of the action"""
+
+
class AppVersionSummaryEvent(BaseModel):
id: str
"""Unique identifier for the app version"""
- actions: List[str]
+ actions: List[AppVersionSummaryEventAction]
"""List of actions available on the app"""
app_name: str
From 8073db60205835e3abb6c494e24bb034283c55f2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 23:13:55 +0000
Subject: [PATCH 11/23] feat(api): update via SDK Studio
---
.stats.yml | 4 ++--
src/kernel/types/deployment_follow_response.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 3ea11ab..3493617 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b8c3224543bfd828075063a87302ec205b54f8b24658cc869b98aa81d995d855.yml
-openapi_spec_hash: 52f5b821303fef54e61bae285f185200
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ba02d679c34c3af5ea47ec2b1a7387785d831e09f35bebfef9f05538ff380c3b.yml
+openapi_spec_hash: 7ddbbe7354f65437d4eb567e8b042552
config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 44a17a6..58203f8 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -70,7 +70,7 @@ class DeploymentStateEvent(BaseModel):
class AppVersionSummaryEventAction(BaseModel):
- name: str
+ name: Optional[str] = None
"""Name of the action"""
From fe8d70b1f0a0725c37c794aeb5a7a466bc13cdf3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Jun 2025 23:14:42 +0000
Subject: [PATCH 12/23] feat(api): update via SDK Studio
---
.stats.yml | 4 ++--
src/kernel/types/deployment_follow_response.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 3493617..bb23445 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ba02d679c34c3af5ea47ec2b1a7387785d831e09f35bebfef9f05538ff380c3b.yml
-openapi_spec_hash: 7ddbbe7354f65437d4eb567e8b042552
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f7fa782f119b02d610bac1dbc75bf8355e73169d978997527f643e24036dabdd.yml
+openapi_spec_hash: 9543dfe156b1c42a2fe4d3767e6b0778
config_hash: a085d1b39ddf0b26ee798501a9f47e20
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 58203f8..44a17a6 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -70,7 +70,7 @@ class DeploymentStateEvent(BaseModel):
class AppVersionSummaryEventAction(BaseModel):
- name: Optional[str] = None
+ name: str
"""Name of the action"""
From 235bf248a71505c9d5d536f1b6a7120e43b9cedc Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 02:39:24 +0000
Subject: [PATCH 13/23] chore(tests): add tests for httpx client instantiation
& proxies
---
tests/test_client.py | 53 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/tests/test_client.py b/tests/test_client.py
index 3a6dcfb..9f38a30 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -27,7 +27,14 @@
from kernel._models import BaseModel, FinalRequestOptions
from kernel._constants import RAW_RESPONSE_HEADER
from kernel._exceptions import KernelError, APIStatusError, APITimeoutError, APIResponseValidationError
-from kernel._base_client import DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, make_request_options
+from kernel._base_client import (
+ DEFAULT_TIMEOUT,
+ HTTPX_DEFAULT_TIMEOUT,
+ BaseClient,
+ DefaultHttpxClient,
+ DefaultAsyncHttpxClient,
+ make_request_options,
+)
from kernel.types.browser_create_params import BrowserCreateParams
from .utils import update_env
@@ -837,6 +844,28 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
+ def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
+ # Test that the proxy environment variables are set correctly
+ monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
+
+ client = DefaultHttpxClient()
+
+ mounts = tuple(client._mounts.items())
+ assert len(mounts) == 1
+ assert mounts[0][0].pattern == "https://"
+
+ @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning")
+ def test_default_client_creation(self) -> None:
+ # Ensure that the client can be initialized without any exceptions
+ DefaultHttpxClient(
+ verify=True,
+ cert=None,
+ trust_env=True,
+ http1=True,
+ http2=False,
+ limits=httpx.Limits(max_connections=100, max_keepalive_connections=20),
+ )
+
@pytest.mark.respx(base_url=base_url)
def test_follow_redirects(self, respx_mock: MockRouter) -> None:
# Test that the default follow_redirects=True allows following redirects
@@ -1716,6 +1745,28 @@ async def test_main() -> None:
time.sleep(0.1)
+ async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
+ # Test that the proxy environment variables are set correctly
+ monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
+
+ client = DefaultAsyncHttpxClient()
+
+ mounts = tuple(client._mounts.items())
+ assert len(mounts) == 1
+ assert mounts[0][0].pattern == "https://"
+
+ @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning")
+ async def test_default_client_creation(self) -> None:
+ # Ensure that the client can be initialized without any exceptions
+ DefaultAsyncHttpxClient(
+ verify=True,
+ cert=None,
+ trust_env=True,
+ http1=True,
+ http2=False,
+ limits=httpx.Limits(max_connections=100, max_keepalive_connections=20),
+ )
+
@pytest.mark.respx(base_url=base_url)
async def test_follow_redirects(self, respx_mock: MockRouter) -> None:
# Test that the default follow_redirects=True allows following redirects
From bcfcef2eb9cd584ad6ec508956d59b34211d2e14 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 04:09:23 +0000
Subject: [PATCH 14/23] chore(internal): update conftest.py
---
tests/conftest.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/conftest.py b/tests/conftest.py
index 6d3cc20..3a11d3f 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,3 +1,5 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
from __future__ import annotations
import os
From fb3fba16b9149449f8327b909210d42ee7744ba4 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 06:39:59 +0000
Subject: [PATCH 15/23] chore(ci): enable for pull requests
---
.github/workflows/ci.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 51b16df..c3f5bc4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,6 +7,10 @@ on:
- 'integrated/**'
- 'stl-preview-head/**'
- 'stl-preview-base/**'
+ pull_request:
+ branches-ignore:
+ - 'stl-preview-head/**'
+ - 'stl-preview-base/**'
jobs:
lint:
From ff0793585ded6d9ea6c50947b9915f560221ed0f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 15:09:43 +0000
Subject: [PATCH 16/23] feat(api): update via SDK Studio
---
.stats.yml | 8 +-
api.md | 20 ++-
src/kernel/_client.py | 10 +-
src/kernel/resources/__init__.py | 14 ++
src/kernel/resources/apps/__init__.py | 14 --
src/kernel/resources/apps/apps.py | 32 ----
.../resources/{apps => }/invocations.py | 115 +++++++++++--
src/kernel/types/__init__.py | 9 ++
src/kernel/types/apps/__init__.py | 5 -
.../types/apps/deployment_follow_response.py | 14 +-
.../types/deployment_follow_response.py | 76 +--------
src/kernel/types/deployment_state_event.py | 46 ++++++
.../{apps => }/invocation_create_params.py | 2 +-
.../{apps => }/invocation_create_response.py | 2 +-
.../types/invocation_follow_response.py | 41 +++++
.../invocation_retrieve_response.py | 2 +-
src/kernel/types/invocation_state_event.py | 57 +++++++
.../{apps => }/invocation_update_params.py | 0
.../{apps => }/invocation_update_response.py | 2 +-
src/kernel/types/shared/__init__.py | 4 +
src/kernel/types/shared/error_detail.py | 15 ++
src/kernel/types/shared/log_event.py | 19 +++
.../{apps => }/test_invocations.py | 152 ++++++++++++++----
23 files changed, 474 insertions(+), 185 deletions(-)
rename src/kernel/resources/{apps => }/invocations.py (75%)
create mode 100644 src/kernel/types/deployment_state_event.py
rename src/kernel/types/{apps => }/invocation_create_params.py (95%)
rename src/kernel/types/{apps => }/invocation_create_response.py (95%)
create mode 100644 src/kernel/types/invocation_follow_response.py
rename src/kernel/types/{apps => }/invocation_retrieve_response.py (97%)
create mode 100644 src/kernel/types/invocation_state_event.py
rename src/kernel/types/{apps => }/invocation_update_params.py (100%)
rename src/kernel/types/{apps => }/invocation_update_response.py (97%)
create mode 100644 src/kernel/types/shared/__init__.py
create mode 100644 src/kernel/types/shared/error_detail.py
create mode 100644 src/kernel/types/shared/log_event.py
rename tests/api_resources/{apps => }/test_invocations.py (65%)
diff --git a/.stats.yml b/.stats.yml
index bb23445..b912099 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 14
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f7fa782f119b02d610bac1dbc75bf8355e73169d978997527f643e24036dabdd.yml
-openapi_spec_hash: 9543dfe156b1c42a2fe4d3767e6b0778
-config_hash: a085d1b39ddf0b26ee798501a9f47e20
+configured_endpoints: 15
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml
+openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f
+config_hash: 4e2f9aebc2153d5caf7bb8b2eb107026
diff --git a/api.md b/api.md
index db76da3..9a7d9a7 100644
--- a/api.md
+++ b/api.md
@@ -1,9 +1,16 @@
+# Shared Types
+
+```python
+from kernel.types import ErrorDetail, LogEvent
+```
+
# Deployments
Types:
```python
from kernel.types import (
+ DeploymentStateEvent,
DeploymentCreateResponse,
DeploymentRetrieveResponse,
DeploymentFollowResponse,
@@ -41,23 +48,26 @@ Methods:
- client.apps.deployments.create(\*\*params) -> DeploymentCreateResponse
- client.apps.deployments.follow(id) -> DeploymentFollowResponse
-## Invocations
+# Invocations
Types:
```python
-from kernel.types.apps import (
+from kernel.types import (
+ InvocationStateEvent,
InvocationCreateResponse,
InvocationRetrieveResponse,
InvocationUpdateResponse,
+ InvocationFollowResponse,
)
```
Methods:
-- client.apps.invocations.create(\*\*params) -> InvocationCreateResponse
-- client.apps.invocations.retrieve(id) -> InvocationRetrieveResponse
-- client.apps.invocations.update(id, \*\*params) -> InvocationUpdateResponse
+- client.invocations.create(\*\*params) -> InvocationCreateResponse
+- client.invocations.retrieve(id) -> InvocationRetrieveResponse
+- client.invocations.update(id, \*\*params) -> InvocationUpdateResponse
+- client.invocations.follow(id) -> InvocationFollowResponse
# Browsers
diff --git a/src/kernel/_client.py b/src/kernel/_client.py
index 084d2a5..63a7dc9 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 browsers, deployments
+from .resources import browsers, deployments, invocations
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import KernelError, APIStatusError
from ._base_client import (
@@ -52,6 +52,7 @@
class Kernel(SyncAPIClient):
deployments: deployments.DeploymentsResource
apps: apps.AppsResource
+ invocations: invocations.InvocationsResource
browsers: browsers.BrowsersResource
with_raw_response: KernelWithRawResponse
with_streaming_response: KernelWithStreamedResponse
@@ -136,6 +137,7 @@ def __init__(
self.deployments = deployments.DeploymentsResource(self)
self.apps = apps.AppsResource(self)
+ self.invocations = invocations.InvocationsResource(self)
self.browsers = browsers.BrowsersResource(self)
self.with_raw_response = KernelWithRawResponse(self)
self.with_streaming_response = KernelWithStreamedResponse(self)
@@ -250,6 +252,7 @@ def _make_status_error(
class AsyncKernel(AsyncAPIClient):
deployments: deployments.AsyncDeploymentsResource
apps: apps.AsyncAppsResource
+ invocations: invocations.AsyncInvocationsResource
browsers: browsers.AsyncBrowsersResource
with_raw_response: AsyncKernelWithRawResponse
with_streaming_response: AsyncKernelWithStreamedResponse
@@ -334,6 +337,7 @@ def __init__(
self.deployments = deployments.AsyncDeploymentsResource(self)
self.apps = apps.AsyncAppsResource(self)
+ self.invocations = invocations.AsyncInvocationsResource(self)
self.browsers = browsers.AsyncBrowsersResource(self)
self.with_raw_response = AsyncKernelWithRawResponse(self)
self.with_streaming_response = AsyncKernelWithStreamedResponse(self)
@@ -449,6 +453,7 @@ class KernelWithRawResponse:
def __init__(self, client: Kernel) -> None:
self.deployments = deployments.DeploymentsResourceWithRawResponse(client.deployments)
self.apps = apps.AppsResourceWithRawResponse(client.apps)
+ self.invocations = invocations.InvocationsResourceWithRawResponse(client.invocations)
self.browsers = browsers.BrowsersResourceWithRawResponse(client.browsers)
@@ -456,6 +461,7 @@ class AsyncKernelWithRawResponse:
def __init__(self, client: AsyncKernel) -> None:
self.deployments = deployments.AsyncDeploymentsResourceWithRawResponse(client.deployments)
self.apps = apps.AsyncAppsResourceWithRawResponse(client.apps)
+ self.invocations = invocations.AsyncInvocationsResourceWithRawResponse(client.invocations)
self.browsers = browsers.AsyncBrowsersResourceWithRawResponse(client.browsers)
@@ -463,6 +469,7 @@ class KernelWithStreamedResponse:
def __init__(self, client: Kernel) -> None:
self.deployments = deployments.DeploymentsResourceWithStreamingResponse(client.deployments)
self.apps = apps.AppsResourceWithStreamingResponse(client.apps)
+ self.invocations = invocations.InvocationsResourceWithStreamingResponse(client.invocations)
self.browsers = browsers.BrowsersResourceWithStreamingResponse(client.browsers)
@@ -470,6 +477,7 @@ class AsyncKernelWithStreamedResponse:
def __init__(self, client: AsyncKernel) -> None:
self.deployments = deployments.AsyncDeploymentsResourceWithStreamingResponse(client.deployments)
self.apps = apps.AsyncAppsResourceWithStreamingResponse(client.apps)
+ self.invocations = invocations.AsyncInvocationsResourceWithStreamingResponse(client.invocations)
self.browsers = browsers.AsyncBrowsersResourceWithStreamingResponse(client.browsers)
diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py
index f65d1db..3b6a4d6 100644
--- a/src/kernel/resources/__init__.py
+++ b/src/kernel/resources/__init__.py
@@ -24,6 +24,14 @@
DeploymentsResourceWithStreamingResponse,
AsyncDeploymentsResourceWithStreamingResponse,
)
+from .invocations import (
+ InvocationsResource,
+ AsyncInvocationsResource,
+ InvocationsResourceWithRawResponse,
+ AsyncInvocationsResourceWithRawResponse,
+ InvocationsResourceWithStreamingResponse,
+ AsyncInvocationsResourceWithStreamingResponse,
+)
__all__ = [
"DeploymentsResource",
@@ -38,6 +46,12 @@
"AsyncAppsResourceWithRawResponse",
"AppsResourceWithStreamingResponse",
"AsyncAppsResourceWithStreamingResponse",
+ "InvocationsResource",
+ "AsyncInvocationsResource",
+ "InvocationsResourceWithRawResponse",
+ "AsyncInvocationsResourceWithRawResponse",
+ "InvocationsResourceWithStreamingResponse",
+ "AsyncInvocationsResourceWithStreamingResponse",
"BrowsersResource",
"AsyncBrowsersResource",
"BrowsersResourceWithRawResponse",
diff --git a/src/kernel/resources/apps/__init__.py b/src/kernel/resources/apps/__init__.py
index 5602ad7..6ce731d 100644
--- a/src/kernel/resources/apps/__init__.py
+++ b/src/kernel/resources/apps/__init__.py
@@ -16,14 +16,6 @@
DeploymentsResourceWithStreamingResponse,
AsyncDeploymentsResourceWithStreamingResponse,
)
-from .invocations import (
- InvocationsResource,
- AsyncInvocationsResource,
- InvocationsResourceWithRawResponse,
- AsyncInvocationsResourceWithRawResponse,
- InvocationsResourceWithStreamingResponse,
- AsyncInvocationsResourceWithStreamingResponse,
-)
__all__ = [
"DeploymentsResource",
@@ -32,12 +24,6 @@
"AsyncDeploymentsResourceWithRawResponse",
"DeploymentsResourceWithStreamingResponse",
"AsyncDeploymentsResourceWithStreamingResponse",
- "InvocationsResource",
- "AsyncInvocationsResource",
- "InvocationsResourceWithRawResponse",
- "AsyncInvocationsResourceWithRawResponse",
- "InvocationsResourceWithStreamingResponse",
- "AsyncInvocationsResourceWithStreamingResponse",
"AppsResource",
"AsyncAppsResource",
"AppsResourceWithRawResponse",
diff --git a/src/kernel/resources/apps/apps.py b/src/kernel/resources/apps/apps.py
index 3769bd5..726db20 100644
--- a/src/kernel/resources/apps/apps.py
+++ b/src/kernel/resources/apps/apps.py
@@ -23,14 +23,6 @@
DeploymentsResourceWithStreamingResponse,
AsyncDeploymentsResourceWithStreamingResponse,
)
-from .invocations import (
- InvocationsResource,
- AsyncInvocationsResource,
- InvocationsResourceWithRawResponse,
- AsyncInvocationsResourceWithRawResponse,
- InvocationsResourceWithStreamingResponse,
- AsyncInvocationsResourceWithStreamingResponse,
-)
from ..._base_client import make_request_options
from ...types.app_list_response import AppListResponse
@@ -42,10 +34,6 @@ class AppsResource(SyncAPIResource):
def deployments(self) -> DeploymentsResource:
return DeploymentsResource(self._client)
- @cached_property
- def invocations(self) -> InvocationsResource:
- return InvocationsResource(self._client)
-
@cached_property
def with_raw_response(self) -> AppsResourceWithRawResponse:
"""
@@ -118,10 +106,6 @@ class AsyncAppsResource(AsyncAPIResource):
def deployments(self) -> AsyncDeploymentsResource:
return AsyncDeploymentsResource(self._client)
- @cached_property
- def invocations(self) -> AsyncInvocationsResource:
- return AsyncInvocationsResource(self._client)
-
@cached_property
def with_raw_response(self) -> AsyncAppsResourceWithRawResponse:
"""
@@ -201,10 +185,6 @@ def __init__(self, apps: AppsResource) -> None:
def deployments(self) -> DeploymentsResourceWithRawResponse:
return DeploymentsResourceWithRawResponse(self._apps.deployments)
- @cached_property
- def invocations(self) -> InvocationsResourceWithRawResponse:
- return InvocationsResourceWithRawResponse(self._apps.invocations)
-
class AsyncAppsResourceWithRawResponse:
def __init__(self, apps: AsyncAppsResource) -> None:
@@ -218,10 +198,6 @@ def __init__(self, apps: AsyncAppsResource) -> None:
def deployments(self) -> AsyncDeploymentsResourceWithRawResponse:
return AsyncDeploymentsResourceWithRawResponse(self._apps.deployments)
- @cached_property
- def invocations(self) -> AsyncInvocationsResourceWithRawResponse:
- return AsyncInvocationsResourceWithRawResponse(self._apps.invocations)
-
class AppsResourceWithStreamingResponse:
def __init__(self, apps: AppsResource) -> None:
@@ -235,10 +211,6 @@ def __init__(self, apps: AppsResource) -> None:
def deployments(self) -> DeploymentsResourceWithStreamingResponse:
return DeploymentsResourceWithStreamingResponse(self._apps.deployments)
- @cached_property
- def invocations(self) -> InvocationsResourceWithStreamingResponse:
- return InvocationsResourceWithStreamingResponse(self._apps.invocations)
-
class AsyncAppsResourceWithStreamingResponse:
def __init__(self, apps: AsyncAppsResource) -> None:
@@ -251,7 +223,3 @@ def __init__(self, apps: AsyncAppsResource) -> None:
@cached_property
def deployments(self) -> AsyncDeploymentsResourceWithStreamingResponse:
return AsyncDeploymentsResourceWithStreamingResponse(self._apps.deployments)
-
- @cached_property
- def invocations(self) -> AsyncInvocationsResourceWithStreamingResponse:
- return AsyncInvocationsResourceWithStreamingResponse(self._apps.invocations)
diff --git a/src/kernel/resources/apps/invocations.py b/src/kernel/resources/invocations.py
similarity index 75%
rename from src/kernel/resources/apps/invocations.py
rename to src/kernel/resources/invocations.py
index b5413d4..c87b8d7 100644
--- a/src/kernel/resources/apps/invocations.py
+++ b/src/kernel/resources/invocations.py
@@ -2,25 +2,28 @@
from __future__ import annotations
+from typing import Any, cast
from typing_extensions import Literal
import httpx
-from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
+from ..types import invocation_create_params, invocation_update_params
+from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+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 ...types.apps import invocation_create_params, invocation_update_params
-from ..._base_client import make_request_options
-from ...types.apps.invocation_create_response import InvocationCreateResponse
-from ...types.apps.invocation_update_response import InvocationUpdateResponse
-from ...types.apps.invocation_retrieve_response import InvocationRetrieveResponse
+from .._streaming import Stream, AsyncStream
+from .._base_client import make_request_options
+from ..types.invocation_create_response import InvocationCreateResponse
+from ..types.invocation_follow_response import InvocationFollowResponse
+from ..types.invocation_update_response import InvocationUpdateResponse
+from ..types.invocation_retrieve_response import InvocationRetrieveResponse
__all__ = ["InvocationsResource", "AsyncInvocationsResource"]
@@ -180,6 +183,46 @@ def update(
cast_to=InvocationUpdateResponse,
)
+ def follow(
+ self,
+ 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,
+ ) -> Stream[InvocationFollowResponse]:
+ """
+ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and
+ status updates for an invocation. The stream terminates automatically once the
+ invocation reaches a terminal state.
+
+ 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:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ return self._get(
+ f"/invocations/{id}/events",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(
+ Any, InvocationFollowResponse
+ ), # Union types cannot be passed in as arguments in the type system
+ stream=True,
+ stream_cls=Stream[InvocationFollowResponse],
+ )
+
class AsyncInvocationsResource(AsyncAPIResource):
@cached_property
@@ -336,6 +379,46 @@ async def update(
cast_to=InvocationUpdateResponse,
)
+ async def follow(
+ self,
+ 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,
+ ) -> AsyncStream[InvocationFollowResponse]:
+ """
+ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and
+ status updates for an invocation. The stream terminates automatically once the
+ invocation reaches a terminal state.
+
+ 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:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ return await self._get(
+ f"/invocations/{id}/events",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(
+ Any, InvocationFollowResponse
+ ), # Union types cannot be passed in as arguments in the type system
+ stream=True,
+ stream_cls=AsyncStream[InvocationFollowResponse],
+ )
+
class InvocationsResourceWithRawResponse:
def __init__(self, invocations: InvocationsResource) -> None:
@@ -350,6 +433,9 @@ def __init__(self, invocations: InvocationsResource) -> None:
self.update = to_raw_response_wrapper(
invocations.update,
)
+ self.follow = to_raw_response_wrapper(
+ invocations.follow,
+ )
class AsyncInvocationsResourceWithRawResponse:
@@ -365,6 +451,9 @@ def __init__(self, invocations: AsyncInvocationsResource) -> None:
self.update = async_to_raw_response_wrapper(
invocations.update,
)
+ self.follow = async_to_raw_response_wrapper(
+ invocations.follow,
+ )
class InvocationsResourceWithStreamingResponse:
@@ -380,6 +469,9 @@ def __init__(self, invocations: InvocationsResource) -> None:
self.update = to_streamed_response_wrapper(
invocations.update,
)
+ self.follow = to_streamed_response_wrapper(
+ invocations.follow,
+ )
class AsyncInvocationsResourceWithStreamingResponse:
@@ -395,3 +487,6 @@ def __init__(self, invocations: AsyncInvocationsResource) -> None:
self.update = async_to_streamed_response_wrapper(
invocations.update,
)
+ self.follow = async_to_streamed_response_wrapper(
+ invocations.follow,
+ )
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index 93a1ee8..4a5c229 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -2,16 +2,25 @@
from __future__ import annotations
+from .shared import LogEvent as LogEvent, ErrorDetail as ErrorDetail
from .app_list_params import AppListParams as AppListParams
from .app_list_response import AppListResponse as AppListResponse
from .browser_persistence import BrowserPersistence as BrowserPersistence
from .browser_create_params import BrowserCreateParams as BrowserCreateParams
from .browser_delete_params import BrowserDeleteParams as BrowserDeleteParams
from .browser_list_response import BrowserListResponse as BrowserListResponse
+from .deployment_state_event import DeploymentStateEvent as DeploymentStateEvent
+from .invocation_state_event import InvocationStateEvent as InvocationStateEvent
from .browser_create_response import BrowserCreateResponse as BrowserCreateResponse
from .deployment_create_params import DeploymentCreateParams as DeploymentCreateParams
+from .invocation_create_params import InvocationCreateParams as InvocationCreateParams
+from .invocation_update_params import InvocationUpdateParams as InvocationUpdateParams
from .browser_persistence_param import BrowserPersistenceParam as BrowserPersistenceParam
from .browser_retrieve_response import BrowserRetrieveResponse as BrowserRetrieveResponse
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 .deployment_retrieve_response import DeploymentRetrieveResponse as DeploymentRetrieveResponse
+from .invocation_retrieve_response import InvocationRetrieveResponse as InvocationRetrieveResponse
diff --git a/src/kernel/types/apps/__init__.py b/src/kernel/types/apps/__init__.py
index f4bf7a2..93aed9d 100644
--- a/src/kernel/types/apps/__init__.py
+++ b/src/kernel/types/apps/__init__.py
@@ -3,10 +3,5 @@
from __future__ import annotations
from .deployment_create_params import DeploymentCreateParams as DeploymentCreateParams
-from .invocation_create_params import InvocationCreateParams as InvocationCreateParams
-from .invocation_update_params import InvocationUpdateParams as InvocationUpdateParams
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_update_response import InvocationUpdateResponse as InvocationUpdateResponse
-from .invocation_retrieve_response import InvocationRetrieveResponse as InvocationRetrieveResponse
diff --git a/src/kernel/types/apps/deployment_follow_response.py b/src/kernel/types/apps/deployment_follow_response.py
index cee006c..fae1b2b 100644
--- a/src/kernel/types/apps/deployment_follow_response.py
+++ b/src/kernel/types/apps/deployment_follow_response.py
@@ -6,8 +6,9 @@
from ..._utils import PropertyInfo
from ..._models import BaseModel
+from ..shared.log_event import LogEvent
-__all__ = ["DeploymentFollowResponse", "StateEvent", "StateUpdateEvent", "LogEvent"]
+__all__ = ["DeploymentFollowResponse", "StateEvent", "StateUpdateEvent"]
class StateEvent(BaseModel):
@@ -34,17 +35,6 @@ class StateUpdateEvent(BaseModel):
"""Time the state change occurred."""
-class LogEvent(BaseModel):
- event: Literal["log"]
- """Event type identifier (always "log")."""
-
- message: str
- """Log message text."""
-
- timestamp: datetime
- """Time the log entry was produced."""
-
-
DeploymentFollowResponse: TypeAlias = Annotated[
Union[StateEvent, StateUpdateEvent, LogEvent], PropertyInfo(discriminator="event")
]
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 44a17a6..38afcad 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -6,69 +6,19 @@
from .._utils import PropertyInfo
from .._models import BaseModel
+from .shared.log_event import LogEvent
+from .shared.error_detail import ErrorDetail
+from .deployment_state_event import DeploymentStateEvent
__all__ = [
"DeploymentFollowResponse",
- "LogEvent",
- "DeploymentStateEvent",
- "DeploymentStateEventDeployment",
"AppVersionSummaryEvent",
"AppVersionSummaryEventAction",
"ErrorEvent",
"ErrorEventError",
- "ErrorEventErrorDetail",
- "ErrorEventErrorInnerError",
]
-class LogEvent(BaseModel):
- event: Literal["log"]
- """Event type identifier (always "log")."""
-
- message: str
- """Log message text."""
-
- timestamp: datetime
- """Time the log entry was produced."""
-
-
-class DeploymentStateEventDeployment(BaseModel):
- id: str
- """Unique identifier for the deployment"""
-
- created_at: datetime
- """Timestamp when the deployment was created"""
-
- region: Literal["aws.us-east-1a"]
- """Deployment region code"""
-
- status: Literal["queued", "in_progress", "running", "failed", "stopped"]
- """Current status of the deployment"""
-
- entrypoint_rel_path: Optional[str] = None
- """Relative path to the application entrypoint"""
-
- env_vars: Optional[Dict[str, str]] = None
- """Environment variables configured for this deployment"""
-
- status_reason: Optional[str] = None
- """Status reason"""
-
- updated_at: Optional[datetime] = None
- """Timestamp when the deployment was last updated"""
-
-
-class DeploymentStateEvent(BaseModel):
- deployment: DeploymentStateEventDeployment
- """Deployment record information."""
-
- event: Literal["deployment_state"]
- """Event type identifier (always "deployment_state")."""
-
- timestamp: datetime
- """Time the state was reported."""
-
-
class AppVersionSummaryEventAction(BaseModel):
name: str
"""Name of the action"""
@@ -100,22 +50,6 @@ class AppVersionSummaryEvent(BaseModel):
"""Environment variables configured for this app version"""
-class ErrorEventErrorDetail(BaseModel):
- code: Optional[str] = None
- """Lower-level error code providing more specific detail"""
-
- message: Optional[str] = None
- """Further detail about the error"""
-
-
-class ErrorEventErrorInnerError(BaseModel):
- code: Optional[str] = None
- """Lower-level error code providing more specific detail"""
-
- message: Optional[str] = None
- """Further detail about the error"""
-
-
class ErrorEventError(BaseModel):
code: str
"""Application-specific error code (machine-readable)"""
@@ -123,10 +57,10 @@ class ErrorEventError(BaseModel):
message: str
"""Human-readable error description for debugging"""
- details: Optional[List[ErrorEventErrorDetail]] = None
+ details: Optional[List[ErrorDetail]] = None
"""Additional error details (for multiple errors)"""
- inner_error: Optional[ErrorEventErrorInnerError] = None
+ inner_error: Optional[ErrorDetail] = None
class ErrorEvent(BaseModel):
diff --git a/src/kernel/types/deployment_state_event.py b/src/kernel/types/deployment_state_event.py
new file mode 100644
index 0000000..572d51b
--- /dev/null
+++ b/src/kernel/types/deployment_state_event.py
@@ -0,0 +1,46 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["DeploymentStateEvent", "Deployment"]
+
+
+class Deployment(BaseModel):
+ id: str
+ """Unique identifier for the deployment"""
+
+ created_at: datetime
+ """Timestamp when the deployment was created"""
+
+ region: Literal["aws.us-east-1a"]
+ """Deployment region code"""
+
+ status: Literal["queued", "in_progress", "running", "failed", "stopped"]
+ """Current status of the deployment"""
+
+ entrypoint_rel_path: Optional[str] = None
+ """Relative path to the application entrypoint"""
+
+ env_vars: Optional[Dict[str, str]] = None
+ """Environment variables configured for this deployment"""
+
+ status_reason: Optional[str] = None
+ """Status reason"""
+
+ updated_at: Optional[datetime] = None
+ """Timestamp when the deployment was last updated"""
+
+
+class DeploymentStateEvent(BaseModel):
+ deployment: Deployment
+ """Deployment record information."""
+
+ event: Literal["deployment_state"]
+ """Event type identifier (always "deployment_state")."""
+
+ timestamp: datetime
+ """Time the state was reported."""
diff --git a/src/kernel/types/apps/invocation_create_params.py b/src/kernel/types/invocation_create_params.py
similarity index 95%
rename from src/kernel/types/apps/invocation_create_params.py
rename to src/kernel/types/invocation_create_params.py
index 01035ae..1d6bc64 100644
--- a/src/kernel/types/apps/invocation_create_params.py
+++ b/src/kernel/types/invocation_create_params.py
@@ -4,7 +4,7 @@
from typing_extensions import Required, Annotated, TypedDict
-from ..._utils import PropertyInfo
+from .._utils import PropertyInfo
__all__ = ["InvocationCreateParams"]
diff --git a/src/kernel/types/apps/invocation_create_response.py b/src/kernel/types/invocation_create_response.py
similarity index 95%
rename from src/kernel/types/apps/invocation_create_response.py
rename to src/kernel/types/invocation_create_response.py
index df4a166..d58f262 100644
--- a/src/kernel/types/apps/invocation_create_response.py
+++ b/src/kernel/types/invocation_create_response.py
@@ -3,7 +3,7 @@
from typing import Optional
from typing_extensions import Literal
-from ..._models import BaseModel
+from .._models import BaseModel
__all__ = ["InvocationCreateResponse"]
diff --git a/src/kernel/types/invocation_follow_response.py b/src/kernel/types/invocation_follow_response.py
new file mode 100644
index 0000000..b1693a1
--- /dev/null
+++ b/src/kernel/types/invocation_follow_response.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .shared.log_event import LogEvent
+from .shared.error_detail import ErrorDetail
+from .invocation_state_event import InvocationStateEvent
+
+__all__ = ["InvocationFollowResponse", "ErrorEvent", "ErrorEventError"]
+
+
+class ErrorEventError(BaseModel):
+ code: str
+ """Application-specific error code (machine-readable)"""
+
+ message: str
+ """Human-readable error description for debugging"""
+
+ details: Optional[List[ErrorDetail]] = None
+ """Additional error details (for multiple errors)"""
+
+ inner_error: Optional[ErrorDetail] = None
+
+
+class ErrorEvent(BaseModel):
+ error: ErrorEventError
+
+ event: Literal["error"]
+ """Event type identifier (always "error")."""
+
+ timestamp: datetime
+ """Time the error occurred."""
+
+
+InvocationFollowResponse: TypeAlias = Annotated[
+ Union[LogEvent, InvocationStateEvent, ErrorEvent], PropertyInfo(discriminator="event")
+]
diff --git a/src/kernel/types/apps/invocation_retrieve_response.py b/src/kernel/types/invocation_retrieve_response.py
similarity index 97%
rename from src/kernel/types/apps/invocation_retrieve_response.py
rename to src/kernel/types/invocation_retrieve_response.py
index f328b14..6626b53 100644
--- a/src/kernel/types/apps/invocation_retrieve_response.py
+++ b/src/kernel/types/invocation_retrieve_response.py
@@ -4,7 +4,7 @@
from datetime import datetime
from typing_extensions import Literal
-from ..._models import BaseModel
+from .._models import BaseModel
__all__ = ["InvocationRetrieveResponse"]
diff --git a/src/kernel/types/invocation_state_event.py b/src/kernel/types/invocation_state_event.py
new file mode 100644
index 0000000..6f30ea6
--- /dev/null
+++ b/src/kernel/types/invocation_state_event.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["InvocationStateEvent", "Invocation"]
+
+
+class Invocation(BaseModel):
+ id: str
+ """ID of the invocation"""
+
+ action_name: str
+ """Name of the action invoked"""
+
+ app_name: str
+ """Name of the application"""
+
+ started_at: datetime
+ """RFC 3339 Nanoseconds timestamp when the invocation started"""
+
+ status: Literal["queued", "running", "succeeded", "failed"]
+ """Status of the invocation"""
+
+ finished_at: Optional[datetime] = None
+ """
+ RFC 3339 Nanoseconds timestamp when the invocation finished (null if still
+ running)
+ """
+
+ output: Optional[str] = None
+ """Output produced by the action, rendered as a JSON string.
+
+ This could be: string, number, boolean, array, object, or null.
+ """
+
+ payload: Optional[str] = None
+ """Payload provided to the invocation.
+
+ This is a string that can be parsed as JSON.
+ """
+
+ status_reason: Optional[str] = None
+ """Status reason"""
+
+
+class InvocationStateEvent(BaseModel):
+ event: Literal["invocation_state"]
+ """Event type identifier (always "invocation_state")."""
+
+ invocation: Invocation
+
+ timestamp: datetime
+ """Time the state was reported."""
diff --git a/src/kernel/types/apps/invocation_update_params.py b/src/kernel/types/invocation_update_params.py
similarity index 100%
rename from src/kernel/types/apps/invocation_update_params.py
rename to src/kernel/types/invocation_update_params.py
diff --git a/src/kernel/types/apps/invocation_update_response.py b/src/kernel/types/invocation_update_response.py
similarity index 97%
rename from src/kernel/types/apps/invocation_update_response.py
rename to src/kernel/types/invocation_update_response.py
index c30fc16..e0029a9 100644
--- a/src/kernel/types/apps/invocation_update_response.py
+++ b/src/kernel/types/invocation_update_response.py
@@ -4,7 +4,7 @@
from datetime import datetime
from typing_extensions import Literal
-from ..._models import BaseModel
+from .._models import BaseModel
__all__ = ["InvocationUpdateResponse"]
diff --git a/src/kernel/types/shared/__init__.py b/src/kernel/types/shared/__init__.py
new file mode 100644
index 0000000..1f139b0
--- /dev/null
+++ b/src/kernel/types/shared/__init__.py
@@ -0,0 +1,4 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .log_event import LogEvent as LogEvent
+from .error_detail import ErrorDetail as ErrorDetail
diff --git a/src/kernel/types/shared/error_detail.py b/src/kernel/types/shared/error_detail.py
new file mode 100644
index 0000000..24e655f
--- /dev/null
+++ b/src/kernel/types/shared/error_detail.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ErrorDetail"]
+
+
+class ErrorDetail(BaseModel):
+ code: Optional[str] = None
+ """Lower-level error code providing more specific detail"""
+
+ message: Optional[str] = None
+ """Further detail about the error"""
diff --git a/src/kernel/types/shared/log_event.py b/src/kernel/types/shared/log_event.py
new file mode 100644
index 0000000..69dbc56
--- /dev/null
+++ b/src/kernel/types/shared/log_event.py
@@ -0,0 +1,19 @@
+# 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__ = ["LogEvent"]
+
+
+class LogEvent(BaseModel):
+ event: Literal["log"]
+ """Event type identifier (always "log")."""
+
+ message: str
+ """Log message text."""
+
+ timestamp: datetime
+ """Time the log entry was produced."""
diff --git a/tests/api_resources/apps/test_invocations.py b/tests/api_resources/test_invocations.py
similarity index 65%
rename from tests/api_resources/apps/test_invocations.py
rename to tests/api_resources/test_invocations.py
index 87dc31f..c11ea7c 100644
--- a/tests/api_resources/apps/test_invocations.py
+++ b/tests/api_resources/test_invocations.py
@@ -9,7 +9,7 @@
from kernel import Kernel, AsyncKernel
from tests.utils import assert_matches_type
-from kernel.types.apps import (
+from kernel.types import (
InvocationCreateResponse,
InvocationUpdateResponse,
InvocationRetrieveResponse,
@@ -24,7 +24,7 @@ class TestInvocations:
@pytest.mark.skip()
@parametrize
def test_method_create(self, client: Kernel) -> None:
- invocation = client.apps.invocations.create(
+ invocation = client.invocations.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -34,7 +34,7 @@ def test_method_create(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_method_create_with_all_params(self, client: Kernel) -> None:
- invocation = client.apps.invocations.create(
+ invocation = client.invocations.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -46,7 +46,7 @@ def test_method_create_with_all_params(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_raw_response_create(self, client: Kernel) -> None:
- response = client.apps.invocations.with_raw_response.create(
+ response = client.invocations.with_raw_response.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -60,7 +60,7 @@ def test_raw_response_create(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_streaming_response_create(self, client: Kernel) -> None:
- with client.apps.invocations.with_streaming_response.create(
+ with client.invocations.with_streaming_response.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -76,7 +76,7 @@ def test_streaming_response_create(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_method_retrieve(self, client: Kernel) -> None:
- invocation = client.apps.invocations.retrieve(
+ invocation = client.invocations.retrieve(
"id",
)
assert_matches_type(InvocationRetrieveResponse, invocation, path=["response"])
@@ -84,7 +84,7 @@ def test_method_retrieve(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_raw_response_retrieve(self, client: Kernel) -> None:
- response = client.apps.invocations.with_raw_response.retrieve(
+ response = client.invocations.with_raw_response.retrieve(
"id",
)
@@ -96,7 +96,7 @@ def test_raw_response_retrieve(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_streaming_response_retrieve(self, client: Kernel) -> None:
- with client.apps.invocations.with_streaming_response.retrieve(
+ with client.invocations.with_streaming_response.retrieve(
"id",
) as response:
assert not response.is_closed
@@ -111,14 +111,14 @@ def test_streaming_response_retrieve(self, client: Kernel) -> None:
@parametrize
def test_path_params_retrieve(self, client: Kernel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.apps.invocations.with_raw_response.retrieve(
+ client.invocations.with_raw_response.retrieve(
"",
)
@pytest.mark.skip()
@parametrize
def test_method_update(self, client: Kernel) -> None:
- invocation = client.apps.invocations.update(
+ invocation = client.invocations.update(
id="id",
status="succeeded",
)
@@ -127,7 +127,7 @@ def test_method_update(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_method_update_with_all_params(self, client: Kernel) -> None:
- invocation = client.apps.invocations.update(
+ invocation = client.invocations.update(
id="id",
status="succeeded",
output="output",
@@ -137,7 +137,7 @@ def test_method_update_with_all_params(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_raw_response_update(self, client: Kernel) -> None:
- response = client.apps.invocations.with_raw_response.update(
+ response = client.invocations.with_raw_response.update(
id="id",
status="succeeded",
)
@@ -150,7 +150,7 @@ def test_raw_response_update(self, client: Kernel) -> None:
@pytest.mark.skip()
@parametrize
def test_streaming_response_update(self, client: Kernel) -> None:
- with client.apps.invocations.with_streaming_response.update(
+ with client.invocations.with_streaming_response.update(
id="id",
status="succeeded",
) as response:
@@ -166,11 +166,60 @@ def test_streaming_response_update(self, client: Kernel) -> None:
@parametrize
def test_path_params_update(self, client: Kernel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.apps.invocations.with_raw_response.update(
+ client.invocations.with_raw_response.update(
id="",
status="succeeded",
)
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_method_follow(self, client: Kernel) -> None:
+ invocation_stream = client.invocations.follow(
+ "id",
+ )
+ invocation_stream.response.close()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_raw_response_follow(self, client: Kernel) -> None:
+ response = client.invocations.with_raw_response.follow(
+ "id",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = response.parse()
+ stream.close()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_streaming_response_follow(self, client: Kernel) -> None:
+ with client.invocations.with_streaming_response.follow(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = response.parse()
+ stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ def test_path_params_follow(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.invocations.with_raw_response.follow(
+ "",
+ )
+
class TestAsyncInvocations:
parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
@@ -178,7 +227,7 @@ class TestAsyncInvocations:
@pytest.mark.skip()
@parametrize
async def test_method_create(self, async_client: AsyncKernel) -> None:
- invocation = await async_client.apps.invocations.create(
+ invocation = await async_client.invocations.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -188,7 +237,7 @@ async def test_method_create(self, async_client: AsyncKernel) -> None:
@pytest.mark.skip()
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> None:
- invocation = await async_client.apps.invocations.create(
+ invocation = await async_client.invocations.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -200,7 +249,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) ->
@pytest.mark.skip()
@parametrize
async def test_raw_response_create(self, async_client: AsyncKernel) -> None:
- response = await async_client.apps.invocations.with_raw_response.create(
+ response = await async_client.invocations.with_raw_response.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -214,7 +263,7 @@ async def test_raw_response_create(self, async_client: AsyncKernel) -> None:
@pytest.mark.skip()
@parametrize
async def test_streaming_response_create(self, async_client: AsyncKernel) -> None:
- async with async_client.apps.invocations.with_streaming_response.create(
+ async with async_client.invocations.with_streaming_response.create(
action_name="analyze",
app_name="my-app",
version="1.0.0",
@@ -230,7 +279,7 @@ async def test_streaming_response_create(self, async_client: AsyncKernel) -> Non
@pytest.mark.skip()
@parametrize
async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
- invocation = await async_client.apps.invocations.retrieve(
+ invocation = await async_client.invocations.retrieve(
"id",
)
assert_matches_type(InvocationRetrieveResponse, invocation, path=["response"])
@@ -238,7 +287,7 @@ async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
@pytest.mark.skip()
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
- response = await async_client.apps.invocations.with_raw_response.retrieve(
+ response = await async_client.invocations.with_raw_response.retrieve(
"id",
)
@@ -250,7 +299,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
@pytest.mark.skip()
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
- async with async_client.apps.invocations.with_streaming_response.retrieve(
+ async with async_client.invocations.with_streaming_response.retrieve(
"id",
) as response:
assert not response.is_closed
@@ -265,14 +314,14 @@ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> N
@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` but received ''"):
- await async_client.apps.invocations.with_raw_response.retrieve(
+ await async_client.invocations.with_raw_response.retrieve(
"",
)
@pytest.mark.skip()
@parametrize
async def test_method_update(self, async_client: AsyncKernel) -> None:
- invocation = await async_client.apps.invocations.update(
+ invocation = await async_client.invocations.update(
id="id",
status="succeeded",
)
@@ -281,7 +330,7 @@ async def test_method_update(self, async_client: AsyncKernel) -> None:
@pytest.mark.skip()
@parametrize
async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> None:
- invocation = await async_client.apps.invocations.update(
+ invocation = await async_client.invocations.update(
id="id",
status="succeeded",
output="output",
@@ -291,7 +340,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) ->
@pytest.mark.skip()
@parametrize
async def test_raw_response_update(self, async_client: AsyncKernel) -> None:
- response = await async_client.apps.invocations.with_raw_response.update(
+ response = await async_client.invocations.with_raw_response.update(
id="id",
status="succeeded",
)
@@ -304,7 +353,7 @@ async def test_raw_response_update(self, async_client: AsyncKernel) -> None:
@pytest.mark.skip()
@parametrize
async def test_streaming_response_update(self, async_client: AsyncKernel) -> None:
- async with async_client.apps.invocations.with_streaming_response.update(
+ async with async_client.invocations.with_streaming_response.update(
id="id",
status="succeeded",
) as response:
@@ -320,7 +369,56 @@ async def test_streaming_response_update(self, async_client: AsyncKernel) -> Non
@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` but received ''"):
- await async_client.apps.invocations.with_raw_response.update(
+ await async_client.invocations.with_raw_response.update(
id="",
status="succeeded",
)
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_method_follow(self, async_client: AsyncKernel) -> None:
+ invocation_stream = await async_client.invocations.follow(
+ "id",
+ )
+ await invocation_stream.response.aclose()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_raw_response_follow(self, async_client: AsyncKernel) -> None:
+ response = await async_client.invocations.with_raw_response.follow(
+ "id",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = await response.parse()
+ await stream.close()
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_streaming_response_follow(self, async_client: AsyncKernel) -> None:
+ async with async_client.invocations.with_streaming_response.follow(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = await response.parse()
+ await stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(
+ reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail"
+ )
+ @parametrize
+ async def test_path_params_follow(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.invocations.with_raw_response.follow(
+ "",
+ )
From d26c519a798d8bf66baaef49af818b4108c3d92a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 15:20:37 +0000
Subject: [PATCH 17/23] feat(api): update via SDK Studio
---
.stats.yml | 6 +--
api.md | 2 +-
src/kernel/types/__init__.py | 2 +-
.../types/deployment_follow_response.py | 33 +----------------
.../types/invocation_follow_response.py | 37 +++----------------
src/kernel/types/shared/__init__.py | 2 +
src/kernel/types/shared/error.py | 21 +++++++++++
src/kernel/types/shared/error_event.py | 19 ++++++++++
8 files changed, 55 insertions(+), 67 deletions(-)
create mode 100644 src/kernel/types/shared/error.py
create mode 100644 src/kernel/types/shared/error_event.py
diff --git a/.stats.yml b/.stats.yml
index b912099..763dad3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 15
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml
-openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f
-config_hash: 4e2f9aebc2153d5caf7bb8b2eb107026
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b1b412b00906fca75bfa73cff7267dbb5bf975581778072e0a90c73ad7ba9cb1.yml
+openapi_spec_hash: 9b7a1b29bcb4963fe6da37005c357d27
+config_hash: df959c379e1145106030a4869b006afe
diff --git a/api.md b/api.md
index 9a7d9a7..b3f657c 100644
--- a/api.md
+++ b/api.md
@@ -1,7 +1,7 @@
# Shared Types
```python
-from kernel.types import ErrorDetail, LogEvent
+from kernel.types import Error, ErrorDetail, ErrorEvent, LogEvent
```
# Deployments
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index 4a5c229..ff41497 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from .shared import LogEvent as LogEvent, ErrorDetail as ErrorDetail
+from .shared import Error as Error, LogEvent as LogEvent, ErrorEvent as ErrorEvent, ErrorDetail as ErrorDetail
from .app_list_params import AppListParams as AppListParams
from .app_list_response import AppListResponse as AppListResponse
from .browser_persistence import BrowserPersistence as BrowserPersistence
diff --git a/src/kernel/types/deployment_follow_response.py b/src/kernel/types/deployment_follow_response.py
index 38afcad..e95ce26 100644
--- a/src/kernel/types/deployment_follow_response.py
+++ b/src/kernel/types/deployment_follow_response.py
@@ -7,16 +7,10 @@
from .._utils import PropertyInfo
from .._models import BaseModel
from .shared.log_event import LogEvent
-from .shared.error_detail import ErrorDetail
+from .shared.error_event import ErrorEvent
from .deployment_state_event import DeploymentStateEvent
-__all__ = [
- "DeploymentFollowResponse",
- "AppVersionSummaryEvent",
- "AppVersionSummaryEventAction",
- "ErrorEvent",
- "ErrorEventError",
-]
+__all__ = ["DeploymentFollowResponse", "AppVersionSummaryEvent", "AppVersionSummaryEventAction"]
class AppVersionSummaryEventAction(BaseModel):
@@ -50,29 +44,6 @@ class AppVersionSummaryEvent(BaseModel):
"""Environment variables configured for this app version"""
-class ErrorEventError(BaseModel):
- code: str
- """Application-specific error code (machine-readable)"""
-
- message: str
- """Human-readable error description for debugging"""
-
- details: Optional[List[ErrorDetail]] = None
- """Additional error details (for multiple errors)"""
-
- inner_error: Optional[ErrorDetail] = None
-
-
-class ErrorEvent(BaseModel):
- error: ErrorEventError
-
- event: Literal["error"]
- """Event type identifier (always "error")."""
-
- timestamp: datetime
- """Time the error occurred."""
-
-
DeploymentFollowResponse: TypeAlias = Annotated[
Union[LogEvent, DeploymentStateEvent, AppVersionSummaryEvent, ErrorEvent], PropertyInfo(discriminator="event")
]
diff --git a/src/kernel/types/invocation_follow_response.py b/src/kernel/types/invocation_follow_response.py
index b1693a1..1abbafc 100644
--- a/src/kernel/types/invocation_follow_response.py
+++ b/src/kernel/types/invocation_follow_response.py
@@ -1,41 +1,16 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List, Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, Annotated, TypeAlias
+from typing import Union
+from typing_extensions import Annotated, TypeAlias
from .._utils import PropertyInfo
-from .._models import BaseModel
from .shared.log_event import LogEvent
-from .shared.error_detail import ErrorDetail
+from .shared.error_event import ErrorEvent
+from .deployment_state_event import DeploymentStateEvent
from .invocation_state_event import InvocationStateEvent
-__all__ = ["InvocationFollowResponse", "ErrorEvent", "ErrorEventError"]
-
-
-class ErrorEventError(BaseModel):
- code: str
- """Application-specific error code (machine-readable)"""
-
- message: str
- """Human-readable error description for debugging"""
-
- details: Optional[List[ErrorDetail]] = None
- """Additional error details (for multiple errors)"""
-
- inner_error: Optional[ErrorDetail] = None
-
-
-class ErrorEvent(BaseModel):
- error: ErrorEventError
-
- event: Literal["error"]
- """Event type identifier (always "error")."""
-
- timestamp: datetime
- """Time the error occurred."""
-
+__all__ = ["InvocationFollowResponse"]
InvocationFollowResponse: TypeAlias = Annotated[
- Union[LogEvent, InvocationStateEvent, ErrorEvent], PropertyInfo(discriminator="event")
+ Union[LogEvent, DeploymentStateEvent, InvocationStateEvent, ErrorEvent], PropertyInfo(discriminator="event")
]
diff --git a/src/kernel/types/shared/__init__.py b/src/kernel/types/shared/__init__.py
index 1f139b0..f7c487b 100644
--- a/src/kernel/types/shared/__init__.py
+++ b/src/kernel/types/shared/__init__.py
@@ -1,4 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .error import Error as Error
from .log_event import LogEvent as LogEvent
+from .error_event import ErrorEvent as ErrorEvent
from .error_detail import ErrorDetail as ErrorDetail
diff --git a/src/kernel/types/shared/error.py b/src/kernel/types/shared/error.py
new file mode 100644
index 0000000..47c8aae
--- /dev/null
+++ b/src/kernel/types/shared/error.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+from .error_detail import ErrorDetail
+
+__all__ = ["Error"]
+
+
+class Error(BaseModel):
+ code: str
+ """Application-specific error code (machine-readable)"""
+
+ message: str
+ """Human-readable error description for debugging"""
+
+ details: Optional[List[ErrorDetail]] = None
+ """Additional error details (for multiple errors)"""
+
+ inner_error: Optional[ErrorDetail] = None
diff --git a/src/kernel/types/shared/error_event.py b/src/kernel/types/shared/error_event.py
new file mode 100644
index 0000000..542634b
--- /dev/null
+++ b/src/kernel/types/shared/error_event.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+from typing_extensions import Literal
+
+from .error import Error
+from ..._models import BaseModel
+
+__all__ = ["ErrorEvent"]
+
+
+class ErrorEvent(BaseModel):
+ error: Error
+
+ event: Literal["error"]
+ """Event type identifier (always "error")."""
+
+ timestamp: datetime
+ """Time the error occurred."""
From dff3e3965fc710beadac2410a8a065d81b889d43 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 15:23:13 +0000
Subject: [PATCH 18/23] feat(api): update via SDK Studio
---
.stats.yml | 4 ++--
src/kernel/types/invocation_follow_response.py | 3 +--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 763dad3..1e9f62b 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 15
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b1b412b00906fca75bfa73cff7267dbb5bf975581778072e0a90c73ad7ba9cb1.yml
-openapi_spec_hash: 9b7a1b29bcb4963fe6da37005c357d27
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml
+openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f
config_hash: df959c379e1145106030a4869b006afe
diff --git a/src/kernel/types/invocation_follow_response.py b/src/kernel/types/invocation_follow_response.py
index 1abbafc..e3d7e8e 100644
--- a/src/kernel/types/invocation_follow_response.py
+++ b/src/kernel/types/invocation_follow_response.py
@@ -6,11 +6,10 @@
from .._utils import PropertyInfo
from .shared.log_event import LogEvent
from .shared.error_event import ErrorEvent
-from .deployment_state_event import DeploymentStateEvent
from .invocation_state_event import InvocationStateEvent
__all__ = ["InvocationFollowResponse"]
InvocationFollowResponse: TypeAlias = Annotated[
- Union[LogEvent, DeploymentStateEvent, InvocationStateEvent, ErrorEvent], PropertyInfo(discriminator="event")
+ Union[LogEvent, InvocationStateEvent, ErrorEvent], PropertyInfo(discriminator="event")
]
From 0c8937a4d8891357223c41fadcb05a6dd1f359b1 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 15:25:14 +0000
Subject: [PATCH 19/23] feat(api): update via SDK Studio
---
.stats.yml | 2 +-
api.md | 2 +-
src/kernel/types/__init__.py | 2 +-
src/kernel/types/shared/__init__.py | 1 -
src/kernel/types/shared/error.py | 21 ---------------------
src/kernel/types/shared/error_event.py | 18 ++++++++++++++++--
6 files changed, 19 insertions(+), 27 deletions(-)
delete mode 100644 src/kernel/types/shared/error.py
diff --git a/.stats.yml b/.stats.yml
index 1e9f62b..71dae95 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 15
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml
openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f
-config_hash: df959c379e1145106030a4869b006afe
+config_hash: 79af9b3bec53ee798dddcf815befa25d
diff --git a/api.md b/api.md
index b3f657c..4574ce7 100644
--- a/api.md
+++ b/api.md
@@ -1,7 +1,7 @@
# Shared Types
```python
-from kernel.types import Error, ErrorDetail, ErrorEvent, LogEvent
+from kernel.types import ErrorDetail, ErrorEvent, LogEvent
```
# Deployments
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index ff41497..87e9ac8 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from .shared import Error as Error, LogEvent as LogEvent, ErrorEvent as ErrorEvent, ErrorDetail as ErrorDetail
+from .shared import LogEvent as LogEvent, ErrorEvent as ErrorEvent, ErrorDetail as ErrorDetail
from .app_list_params import AppListParams as AppListParams
from .app_list_response import AppListResponse as AppListResponse
from .browser_persistence import BrowserPersistence as BrowserPersistence
diff --git a/src/kernel/types/shared/__init__.py b/src/kernel/types/shared/__init__.py
index f7c487b..45c73b3 100644
--- a/src/kernel/types/shared/__init__.py
+++ b/src/kernel/types/shared/__init__.py
@@ -1,6 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from .error import Error as Error
from .log_event import LogEvent as LogEvent
from .error_event import ErrorEvent as ErrorEvent
from .error_detail import ErrorDetail as ErrorDetail
diff --git a/src/kernel/types/shared/error.py b/src/kernel/types/shared/error.py
deleted file mode 100644
index 47c8aae..0000000
--- a/src/kernel/types/shared/error.py
+++ /dev/null
@@ -1,21 +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 .error_detail import ErrorDetail
-
-__all__ = ["Error"]
-
-
-class Error(BaseModel):
- code: str
- """Application-specific error code (machine-readable)"""
-
- message: str
- """Human-readable error description for debugging"""
-
- details: Optional[List[ErrorDetail]] = None
- """Additional error details (for multiple errors)"""
-
- inner_error: Optional[ErrorDetail] = None
diff --git a/src/kernel/types/shared/error_event.py b/src/kernel/types/shared/error_event.py
index 542634b..172a8be 100644
--- a/src/kernel/types/shared/error_event.py
+++ b/src/kernel/types/shared/error_event.py
@@ -1,12 +1,26 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from typing import List, Optional
from datetime import datetime
from typing_extensions import Literal
-from .error import Error
from ..._models import BaseModel
+from .error_detail import ErrorDetail
-__all__ = ["ErrorEvent"]
+__all__ = ["ErrorEvent", "Error"]
+
+
+class Error(BaseModel):
+ code: str
+ """Application-specific error code (machine-readable)"""
+
+ message: str
+ """Human-readable error description for debugging"""
+
+ details: Optional[List[ErrorDetail]] = None
+ """Additional error details (for multiple errors)"""
+
+ inner_error: Optional[ErrorDetail] = None
class ErrorEvent(BaseModel):
From a81101709db8cb64b4cb6af6b749b55f86c24be6 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 15:25:57 +0000
Subject: [PATCH 20/23] feat(api): update via SDK Studio
---
.stats.yml | 2 +-
api.md | 2 +-
src/kernel/types/__init__.py | 2 +-
src/kernel/types/shared/__init__.py | 1 +
src/kernel/types/shared/error_event.py | 20 +++-----------------
src/kernel/types/shared/error_model.py | 21 +++++++++++++++++++++
6 files changed, 28 insertions(+), 20 deletions(-)
create mode 100644 src/kernel/types/shared/error_model.py
diff --git a/.stats.yml b/.stats.yml
index 71dae95..ba1c7c9 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 15
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml
openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f
-config_hash: 79af9b3bec53ee798dddcf815befa25d
+config_hash: 0fdf285ddd8dee229fd84ea57df9080f
diff --git a/api.md b/api.md
index 4574ce7..cb25dcb 100644
--- a/api.md
+++ b/api.md
@@ -1,7 +1,7 @@
# Shared Types
```python
-from kernel.types import ErrorDetail, ErrorEvent, LogEvent
+from kernel.types import ErrorDetail, ErrorEvent, ErrorModel, LogEvent
```
# Deployments
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index 87e9ac8..cf2dbbc 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from .shared import LogEvent as LogEvent, ErrorEvent as ErrorEvent, ErrorDetail as ErrorDetail
+from .shared import LogEvent as LogEvent, ErrorEvent as ErrorEvent, ErrorModel as ErrorModel, ErrorDetail as ErrorDetail
from .app_list_params import AppListParams as AppListParams
from .app_list_response import AppListResponse as AppListResponse
from .browser_persistence import BrowserPersistence as BrowserPersistence
diff --git a/src/kernel/types/shared/__init__.py b/src/kernel/types/shared/__init__.py
index 45c73b3..e444e22 100644
--- a/src/kernel/types/shared/__init__.py
+++ b/src/kernel/types/shared/__init__.py
@@ -2,4 +2,5 @@
from .log_event import LogEvent as LogEvent
from .error_event import ErrorEvent as ErrorEvent
+from .error_model import ErrorModel as ErrorModel
from .error_detail import ErrorDetail as ErrorDetail
diff --git a/src/kernel/types/shared/error_event.py b/src/kernel/types/shared/error_event.py
index 172a8be..0041b89 100644
--- a/src/kernel/types/shared/error_event.py
+++ b/src/kernel/types/shared/error_event.py
@@ -1,30 +1,16 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List, Optional
from datetime import datetime
from typing_extensions import Literal
from ..._models import BaseModel
-from .error_detail import ErrorDetail
+from .error_model import ErrorModel
-__all__ = ["ErrorEvent", "Error"]
-
-
-class Error(BaseModel):
- code: str
- """Application-specific error code (machine-readable)"""
-
- message: str
- """Human-readable error description for debugging"""
-
- details: Optional[List[ErrorDetail]] = None
- """Additional error details (for multiple errors)"""
-
- inner_error: Optional[ErrorDetail] = None
+__all__ = ["ErrorEvent"]
class ErrorEvent(BaseModel):
- error: Error
+ error: ErrorModel
event: Literal["error"]
"""Event type identifier (always "error")."""
diff --git a/src/kernel/types/shared/error_model.py b/src/kernel/types/shared/error_model.py
new file mode 100644
index 0000000..6cb4811
--- /dev/null
+++ b/src/kernel/types/shared/error_model.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+from .error_detail import ErrorDetail
+
+__all__ = ["ErrorModel"]
+
+
+class ErrorModel(BaseModel):
+ code: str
+ """Application-specific error code (machine-readable)"""
+
+ message: str
+ """Human-readable error description for debugging"""
+
+ details: Optional[List[ErrorDetail]] = None
+ """Additional error details (for multiple errors)"""
+
+ inner_error: Optional[ErrorDetail] = None
From 099868c0c2fbb92a4b9e97cda89bf4e71781d76f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 18 Jun 2025 02:12:12 +0000
Subject: [PATCH 21/23] chore(readme): update badges
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 9d3c4fa..fa501ab 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Kernel Python API library
-[](https://pypi.org/project/kernel/)
+[![PyPI version]()](https://pypi.org/project/kernel/)
The Kernel Python library provides convenient access to the Kernel REST API from any Python 3.8+
application. The library includes type definitions for all request params and response fields,
From 53d65471447af6f764aa48bd708c540215c8fd4a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 18 Jun 2025 05:49:09 +0000
Subject: [PATCH 22/23] fix(tests): fix: tests which call HTTP endpoints
directly with the example parameters
---
tests/test_client.py | 69 ++++++++------------------------------------
1 file changed, 12 insertions(+), 57 deletions(-)
diff --git a/tests/test_client.py b/tests/test_client.py
index 9f38a30..dea2c81 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -23,9 +23,7 @@
from kernel import Kernel, AsyncKernel, APIResponseValidationError
from kernel._types import Omit
-from kernel._utils import maybe_transform
from kernel._models import BaseModel, FinalRequestOptions
-from kernel._constants import RAW_RESPONSE_HEADER
from kernel._exceptions import KernelError, APIStatusError, APITimeoutError, APIResponseValidationError
from kernel._base_client import (
DEFAULT_TIMEOUT,
@@ -35,7 +33,6 @@
DefaultAsyncHttpxClient,
make_request_options,
)
-from kernel.types.browser_create_params import BrowserCreateParams
from .utils import update_env
@@ -722,45 +719,22 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str
@pytest.mark.skip() # SDK-2615
@mock.patch("kernel._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
@pytest.mark.respx(base_url=base_url)
- def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
+ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: Kernel) -> None:
respx_mock.post("/browsers").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- self.client.post(
- "/browsers",
- body=cast(
- object,
- maybe_transform(
- dict(invocation_id="REPLACE_ME", persistence={"id": "browser-for-user-1234"}),
- BrowserCreateParams,
- ),
- ),
- cast_to=httpx.Response,
- options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
- )
+ client.browsers.with_streaming_response.create(invocation_id="rr33xuugxj9h0bkf1rdt2bet").__enter__()
assert _get_open_connections(self.client) == 0
@pytest.mark.skip() # SDK-2615
@mock.patch("kernel._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
@pytest.mark.respx(base_url=base_url)
- def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
+ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: Kernel) -> None:
respx_mock.post("/browsers").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- self.client.post(
- "/browsers",
- body=cast(
- object,
- maybe_transform(
- dict(invocation_id="REPLACE_ME", persistence={"id": "browser-for-user-1234"}),
- BrowserCreateParams,
- ),
- ),
- cast_to=httpx.Response,
- options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
- )
-
+ client.browsers.with_streaming_response.create(invocation_id="rr33xuugxj9h0bkf1rdt2bet").__enter__()
assert _get_open_connections(self.client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1575,45 +1549,26 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte
@pytest.mark.skip() # SDK-2615
@mock.patch("kernel._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
@pytest.mark.respx(base_url=base_url)
- async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
+ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, async_client: AsyncKernel) -> None:
respx_mock.post("/browsers").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- await self.client.post(
- "/browsers",
- body=cast(
- object,
- maybe_transform(
- dict(invocation_id="REPLACE_ME", persistence={"id": "browser-for-user-1234"}),
- BrowserCreateParams,
- ),
- ),
- cast_to=httpx.Response,
- options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
- )
+ await async_client.browsers.with_streaming_response.create(
+ invocation_id="rr33xuugxj9h0bkf1rdt2bet"
+ ).__aenter__()
assert _get_open_connections(self.client) == 0
@pytest.mark.skip() # SDK-2615
@mock.patch("kernel._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
@pytest.mark.respx(base_url=base_url)
- async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
+ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, async_client: AsyncKernel) -> None:
respx_mock.post("/browsers").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- await self.client.post(
- "/browsers",
- body=cast(
- object,
- maybe_transform(
- dict(invocation_id="REPLACE_ME", persistence={"id": "browser-for-user-1234"}),
- BrowserCreateParams,
- ),
- ),
- cast_to=httpx.Response,
- options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
- )
-
+ await async_client.browsers.with_streaming_response.create(
+ invocation_id="rr33xuugxj9h0bkf1rdt2bet"
+ ).__aenter__()
assert _get_open_connections(self.client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
From 834f1e989392f4f15b88689fef81fbe3d7b071f4 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 18 Jun 2025 05:49:30 +0000
Subject: [PATCH 23/23] release: 0.6.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 35 +++++++++++++++++++++++++++++++++++
pyproject.toml | 2 +-
src/kernel/_version.py | 2 +-
4 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 2aca35a..4208b5c 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.5.0"
+ ".": "0.6.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 462f762..25d053c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,40 @@
# Changelog
+## 0.6.0 (2025-06-18)
+
+Full Changelog: [v0.5.0...v0.6.0](https://github.com/onkernel/kernel-python-sdk/compare/v0.5.0...v0.6.0)
+
+### Features
+
+* **api:** update via SDK Studio ([a811017](https://github.com/onkernel/kernel-python-sdk/commit/a81101709db8cb64b4cb6af6b749b55f86c24be6))
+* **api:** update via SDK Studio ([0c8937a](https://github.com/onkernel/kernel-python-sdk/commit/0c8937a4d8891357223c41fadcb05a6dd1f359b1))
+* **api:** update via SDK Studio ([dff3e39](https://github.com/onkernel/kernel-python-sdk/commit/dff3e3965fc710beadac2410a8a065d81b889d43))
+* **api:** update via SDK Studio ([d26c519](https://github.com/onkernel/kernel-python-sdk/commit/d26c519a798d8bf66baaef49af818b4108c3d92a))
+* **api:** update via SDK Studio ([ff07935](https://github.com/onkernel/kernel-python-sdk/commit/ff0793585ded6d9ea6c50947b9915f560221ed0f))
+* **api:** update via SDK Studio ([fe8d70b](https://github.com/onkernel/kernel-python-sdk/commit/fe8d70b1f0a0725c37c794aeb5a7a466bc13cdf3))
+* **api:** update via SDK Studio ([8073db6](https://github.com/onkernel/kernel-python-sdk/commit/8073db60205835e3abb6c494e24bb034283c55f2))
+* **api:** update via SDK Studio ([c1cdbcc](https://github.com/onkernel/kernel-python-sdk/commit/c1cdbcc6e555ab5fc7ecc229095ff7d0bf272e1a))
+* **api:** update via SDK Studio ([eed8e67](https://github.com/onkernel/kernel-python-sdk/commit/eed8e6769fd4982cadb277aa4c271c211992077a))
+* **api:** update via SDK Studio ([7699111](https://github.com/onkernel/kernel-python-sdk/commit/76991114e757c0c054e89d614619e38b2ec7d918))
+* **api:** update via SDK Studio ([d51332b](https://github.com/onkernel/kernel-python-sdk/commit/d51332b18af547affb215d9a7596bbbdb7ccff24))
+* **api:** update via SDK Studio ([452e83c](https://github.com/onkernel/kernel-python-sdk/commit/452e83c41d808b97e1ff54cdfa79d74abccfc9b5))
+* **api:** update via SDK Studio ([496e5cd](https://github.com/onkernel/kernel-python-sdk/commit/496e5cd31745446c16234120f9299be4a9830bb5))
+
+
+### Bug Fixes
+
+* **client:** correctly parse binary response | stream ([0079349](https://github.com/onkernel/kernel-python-sdk/commit/007934910a1ec8e17a6be821feacef9b42a2c142))
+* **tests:** fix: tests which call HTTP endpoints directly with the example parameters ([53d6547](https://github.com/onkernel/kernel-python-sdk/commit/53d65471447af6f764aa48bd708c540215c8fd4a))
+
+
+### Chores
+
+* **ci:** enable for pull requests ([fb3fba1](https://github.com/onkernel/kernel-python-sdk/commit/fb3fba16b9149449f8327b909210d42ee7744ba4))
+* **internal:** update conftest.py ([bcfcef2](https://github.com/onkernel/kernel-python-sdk/commit/bcfcef2eb9cd584ad6ec508956d59b34211d2e14))
+* **readme:** update badges ([099868c](https://github.com/onkernel/kernel-python-sdk/commit/099868c0c2fbb92a4b9e97cda89bf4e71781d76f))
+* **tests:** add tests for httpx client instantiation & proxies ([235bf24](https://github.com/onkernel/kernel-python-sdk/commit/235bf248a71505c9d5d536f1b6a7120e43b9cedc))
+* **tests:** run tests in parallel ([83e4f2c](https://github.com/onkernel/kernel-python-sdk/commit/83e4f2c26f02a7df56917e993af1e1d85ba241e6))
+
## 0.5.0 (2025-06-03)
Full Changelog: [v0.4.0...v0.5.0](https://github.com/onkernel/kernel-python-sdk/compare/v0.4.0...v0.5.0)
diff --git a/pyproject.toml b/pyproject.toml
index ce8b48d..3bfd297 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "kernel"
-version = "0.5.0"
+version = "0.6.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 2c947c2..c6e626d 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.5.0" # x-release-please-version
+__version__ = "0.6.0" # x-release-please-version