diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 95e4ab67..53327971 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.11.2"
+ ".": "0.11.3"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 385372f3..4039b103 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 50
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d3a597bbbb25c131e2c06eb9b47d70932d14a97a6f916677a195a128e196f4db.yml
-openapi_spec_hash: c967b384624017eed0abff1b53a74530
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5ee2116982adf46664acf84b8ba4b56ba65780983506c63d9b005dab49def757.yml
+openapi_spec_hash: 42a3a519301d0e2bb2b5a71018915b55
config_hash: 0d150b61cae2dc57d3648ceae7784966
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5772793b..adcaaf22 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.11.3 (2025-09-24)
+
+Full Changelog: [v0.11.2...v0.11.3](https://github.com/onkernel/kernel-python-sdk/compare/v0.11.2...v0.11.3)
+
+### Features
+
+* Per Invocation Logs ([8c116b6](https://github.com/onkernel/kernel-python-sdk/commit/8c116b6e8590709dab14961b7e9c038229f5ace5))
+
## 0.11.2 (2025-09-24)
Full Changelog: [v0.11.1...v0.11.2](https://github.com/onkernel/kernel-python-sdk/compare/v0.11.1...v0.11.2)
diff --git a/api.md b/api.md
index 21ccdb73..eaef5078 100644
--- a/api.md
+++ b/api.md
@@ -57,7 +57,7 @@ Methods:
- client.invocations.retrieve(id) -> InvocationRetrieveResponse
- client.invocations.update(id, \*\*params) -> InvocationUpdateResponse
- client.invocations.delete_browsers(id) -> None
-- client.invocations.follow(id) -> InvocationFollowResponse
+- client.invocations.follow(id, \*\*params) -> InvocationFollowResponse
# Browsers
diff --git a/pyproject.toml b/pyproject.toml
index f6c58357..e5bcc8f8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "kernel"
-version = "0.11.2"
+version = "0.11.3"
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 a0cd88ab..408c4e47 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.11.2" # x-release-please-version
+__version__ = "0.11.3" # x-release-please-version
diff --git a/src/kernel/resources/invocations.py b/src/kernel/resources/invocations.py
index 8b5c1bc4..4d671646 100644
--- a/src/kernel/resources/invocations.py
+++ b/src/kernel/resources/invocations.py
@@ -7,7 +7,7 @@
import httpx
-from ..types import invocation_create_params, invocation_update_params
+from ..types import invocation_create_params, invocation_follow_params, invocation_update_params
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -223,6 +223,7 @@ def follow(
self,
id: str,
*,
+ since: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -236,6 +237,8 @@ def follow(
invocation reaches a terminal state.
Args:
+ since: Show logs since the given time (RFC timestamps or durations like 5m).
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -250,7 +253,11 @@ def follow(
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
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"since": since}, invocation_follow_params.InvocationFollowParams),
),
cast_to=cast(
Any, InvocationFollowResponse
@@ -455,6 +462,7 @@ async def follow(
self,
id: str,
*,
+ since: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -468,6 +476,8 @@ async def follow(
invocation reaches a terminal state.
Args:
+ since: Show logs since the given time (RFC timestamps or durations like 5m).
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -482,7 +492,11 @@ async def follow(
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
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform({"since": since}, invocation_follow_params.InvocationFollowParams),
),
cast_to=cast(
Any, InvocationFollowResponse
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index e571af62..0eae67cb 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -31,6 +31,7 @@
from .deployment_follow_params import DeploymentFollowParams as DeploymentFollowParams
from .deployment_list_response import DeploymentListResponse as DeploymentListResponse
from .invocation_create_params import InvocationCreateParams as InvocationCreateParams
+from .invocation_follow_params import InvocationFollowParams as InvocationFollowParams
from .invocation_update_params import InvocationUpdateParams as InvocationUpdateParams
from .browser_persistence_param import BrowserPersistenceParam as BrowserPersistenceParam
from .browser_retrieve_response import BrowserRetrieveResponse as BrowserRetrieveResponse
diff --git a/src/kernel/types/invocation_follow_params.py b/src/kernel/types/invocation_follow_params.py
new file mode 100644
index 00000000..67847810
--- /dev/null
+++ b/src/kernel/types/invocation_follow_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["InvocationFollowParams"]
+
+
+class InvocationFollowParams(TypedDict, total=False):
+ since: str
+ """Show logs since the given time (RFC timestamps or durations like 5m)."""
diff --git a/tests/api_resources/test_invocations.py b/tests/api_resources/test_invocations.py
index 38734f85..ae3b451b 100644
--- a/tests/api_resources/test_invocations.py
+++ b/tests/api_resources/test_invocations.py
@@ -217,7 +217,16 @@ def test_path_params_delete_browsers(self, client: Kernel) -> None:
@parametrize
def test_method_follow(self, client: Kernel) -> None:
invocation_stream = client.invocations.follow(
- "id",
+ id="id",
+ )
+ invocation_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_follow_with_all_params(self, client: Kernel) -> None:
+ invocation_stream = client.invocations.follow(
+ id="id",
+ since="2025-06-20T12:00:00Z",
)
invocation_stream.response.close()
@@ -225,7 +234,7 @@ def test_method_follow(self, client: Kernel) -> None:
@parametrize
def test_raw_response_follow(self, client: Kernel) -> None:
response = client.invocations.with_raw_response.follow(
- "id",
+ id="id",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -236,7 +245,7 @@ def test_raw_response_follow(self, client: Kernel) -> None:
@parametrize
def test_streaming_response_follow(self, client: Kernel) -> None:
with client.invocations.with_streaming_response.follow(
- "id",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -251,7 +260,7 @@ def test_streaming_response_follow(self, client: Kernel) -> None:
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(
- "",
+ id="",
)
@@ -456,7 +465,16 @@ async def test_path_params_delete_browsers(self, async_client: AsyncKernel) -> N
@parametrize
async def test_method_follow(self, async_client: AsyncKernel) -> None:
invocation_stream = await async_client.invocations.follow(
- "id",
+ id="id",
+ )
+ await invocation_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_follow_with_all_params(self, async_client: AsyncKernel) -> None:
+ invocation_stream = await async_client.invocations.follow(
+ id="id",
+ since="2025-06-20T12:00:00Z",
)
await invocation_stream.response.aclose()
@@ -464,7 +482,7 @@ async def test_method_follow(self, async_client: AsyncKernel) -> None:
@parametrize
async def test_raw_response_follow(self, async_client: AsyncKernel) -> None:
response = await async_client.invocations.with_raw_response.follow(
- "id",
+ id="id",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -475,7 +493,7 @@ async def test_raw_response_follow(self, async_client: AsyncKernel) -> None:
@parametrize
async def test_streaming_response_follow(self, async_client: AsyncKernel) -> None:
async with async_client.invocations.with_streaming_response.follow(
- "id",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -490,5 +508,5 @@ async def test_streaming_response_follow(self, async_client: AsyncKernel) -> Non
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(
- "",
+ id="",
)