Skip to content

Commit aaa43f3

Browse files
feat: Per Invocation Logs
1 parent 7030d45 commit aaa43f3

File tree

6 files changed

+59
-14
lines changed

6 files changed

+59
-14
lines changed

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 50
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d3a597bbbb25c131e2c06eb9b47d70932d14a97a6f916677a195a128e196f4db.yml
3-
openapi_spec_hash: c967b384624017eed0abff1b53a74530
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5ee2116982adf46664acf84b8ba4b56ba65780983506c63d9b005dab49def757.yml
3+
openapi_spec_hash: 42a3a519301d0e2bb2b5a71018915b55
44
config_hash: 0d150b61cae2dc57d3648ceae7784966

api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Methods:
5757
- <code title="get /invocations/{id}">client.invocations.<a href="./src/kernel/resources/invocations.py">retrieve</a>(id) -> <a href="./src/kernel/types/invocation_retrieve_response.py">InvocationRetrieveResponse</a></code>
5858
- <code title="patch /invocations/{id}">client.invocations.<a href="./src/kernel/resources/invocations.py">update</a>(id, \*\*<a href="src/kernel/types/invocation_update_params.py">params</a>) -> <a href="./src/kernel/types/invocation_update_response.py">InvocationUpdateResponse</a></code>
5959
- <code title="delete /invocations/{id}/browsers">client.invocations.<a href="./src/kernel/resources/invocations.py">delete_browsers</a>(id) -> None</code>
60-
- <code title="get /invocations/{id}/events">client.invocations.<a href="./src/kernel/resources/invocations.py">follow</a>(id) -> <a href="./src/kernel/types/invocation_follow_response.py">InvocationFollowResponse</a></code>
60+
- <code title="get /invocations/{id}/events">client.invocations.<a href="./src/kernel/resources/invocations.py">follow</a>(id, \*\*<a href="src/kernel/types/invocation_follow_params.py">params</a>) -> <a href="./src/kernel/types/invocation_follow_response.py">InvocationFollowResponse</a></code>
6161

6262
# Browsers
6363

src/kernel/resources/invocations.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import httpx
99

10-
from ..types import invocation_create_params, invocation_update_params
10+
from ..types import invocation_create_params, invocation_follow_params, invocation_update_params
1111
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
1212
from .._utils import maybe_transform, async_maybe_transform
1313
from .._compat import cached_property
@@ -223,6 +223,7 @@ def follow(
223223
self,
224224
id: str,
225225
*,
226+
since: str | Omit = omit,
226227
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
227228
# The extra values given here take precedence over values defined on the client or passed to this method.
228229
extra_headers: Headers | None = None,
@@ -236,6 +237,8 @@ def follow(
236237
invocation reaches a terminal state.
237238
238239
Args:
240+
since: Show logs since the given time (RFC timestamps or durations like 5m).
241+
239242
extra_headers: Send extra headers
240243
241244
extra_query: Add additional query parameters to the request
@@ -250,7 +253,11 @@ def follow(
250253
return self._get(
251254
f"/invocations/{id}/events",
252255
options=make_request_options(
253-
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
256+
extra_headers=extra_headers,
257+
extra_query=extra_query,
258+
extra_body=extra_body,
259+
timeout=timeout,
260+
query=maybe_transform({"since": since}, invocation_follow_params.InvocationFollowParams),
254261
),
255262
cast_to=cast(
256263
Any, InvocationFollowResponse
@@ -455,6 +462,7 @@ async def follow(
455462
self,
456463
id: str,
457464
*,
465+
since: str | Omit = omit,
458466
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
459467
# The extra values given here take precedence over values defined on the client or passed to this method.
460468
extra_headers: Headers | None = None,
@@ -468,6 +476,8 @@ async def follow(
468476
invocation reaches a terminal state.
469477
470478
Args:
479+
since: Show logs since the given time (RFC timestamps or durations like 5m).
480+
471481
extra_headers: Send extra headers
472482
473483
extra_query: Add additional query parameters to the request
@@ -482,7 +492,11 @@ async def follow(
482492
return await self._get(
483493
f"/invocations/{id}/events",
484494
options=make_request_options(
485-
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
495+
extra_headers=extra_headers,
496+
extra_query=extra_query,
497+
extra_body=extra_body,
498+
timeout=timeout,
499+
query=await async_maybe_transform({"since": since}, invocation_follow_params.InvocationFollowParams),
486500
),
487501
cast_to=cast(
488502
Any, InvocationFollowResponse

src/kernel/types/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from .deployment_follow_params import DeploymentFollowParams as DeploymentFollowParams
3232
from .deployment_list_response import DeploymentListResponse as DeploymentListResponse
3333
from .invocation_create_params import InvocationCreateParams as InvocationCreateParams
34+
from .invocation_follow_params import InvocationFollowParams as InvocationFollowParams
3435
from .invocation_update_params import InvocationUpdateParams as InvocationUpdateParams
3536
from .browser_persistence_param import BrowserPersistenceParam as BrowserPersistenceParam
3637
from .browser_retrieve_response import BrowserRetrieveResponse as BrowserRetrieveResponse
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing_extensions import TypedDict
6+
7+
__all__ = ["InvocationFollowParams"]
8+
9+
10+
class InvocationFollowParams(TypedDict, total=False):
11+
since: str
12+
"""Show logs since the given time (RFC timestamps or durations like 5m)."""

tests/api_resources/test_invocations.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,24 @@ def test_path_params_delete_browsers(self, client: Kernel) -> None:
217217
@parametrize
218218
def test_method_follow(self, client: Kernel) -> None:
219219
invocation_stream = client.invocations.follow(
220-
"id",
220+
id="id",
221+
)
222+
invocation_stream.response.close()
223+
224+
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
225+
@parametrize
226+
def test_method_follow_with_all_params(self, client: Kernel) -> None:
227+
invocation_stream = client.invocations.follow(
228+
id="id",
229+
since="2025-06-20T12:00:00Z",
221230
)
222231
invocation_stream.response.close()
223232

224233
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
225234
@parametrize
226235
def test_raw_response_follow(self, client: Kernel) -> None:
227236
response = client.invocations.with_raw_response.follow(
228-
"id",
237+
id="id",
229238
)
230239

231240
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -236,7 +245,7 @@ def test_raw_response_follow(self, client: Kernel) -> None:
236245
@parametrize
237246
def test_streaming_response_follow(self, client: Kernel) -> None:
238247
with client.invocations.with_streaming_response.follow(
239-
"id",
248+
id="id",
240249
) as response:
241250
assert not response.is_closed
242251
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -251,7 +260,7 @@ def test_streaming_response_follow(self, client: Kernel) -> None:
251260
def test_path_params_follow(self, client: Kernel) -> None:
252261
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
253262
client.invocations.with_raw_response.follow(
254-
"",
263+
id="",
255264
)
256265

257266

@@ -456,15 +465,24 @@ async def test_path_params_delete_browsers(self, async_client: AsyncKernel) -> N
456465
@parametrize
457466
async def test_method_follow(self, async_client: AsyncKernel) -> None:
458467
invocation_stream = await async_client.invocations.follow(
459-
"id",
468+
id="id",
469+
)
470+
await invocation_stream.response.aclose()
471+
472+
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
473+
@parametrize
474+
async def test_method_follow_with_all_params(self, async_client: AsyncKernel) -> None:
475+
invocation_stream = await async_client.invocations.follow(
476+
id="id",
477+
since="2025-06-20T12:00:00Z",
460478
)
461479
await invocation_stream.response.aclose()
462480

463481
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
464482
@parametrize
465483
async def test_raw_response_follow(self, async_client: AsyncKernel) -> None:
466484
response = await async_client.invocations.with_raw_response.follow(
467-
"id",
485+
id="id",
468486
)
469487

470488
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:
475493
@parametrize
476494
async def test_streaming_response_follow(self, async_client: AsyncKernel) -> None:
477495
async with async_client.invocations.with_streaming_response.follow(
478-
"id",
496+
id="id",
479497
) as response:
480498
assert not response.is_closed
481499
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
490508
async def test_path_params_follow(self, async_client: AsyncKernel) -> None:
491509
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
492510
await async_client.invocations.with_raw_response.follow(
493-
"",
511+
id="",
494512
)

0 commit comments

Comments
 (0)