Skip to content

Commit ebdae79

Browse files
Merge remote-tracking branch 'origin/main' into stlc/promote-next
2 parents f84af42 + 755dba5 commit ebdae79

11 files changed

Lines changed: 391 additions & 11 deletions

File tree

‎.stats.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
configured_endpoints: 164
1+
configured_endpoints: 165

‎api.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ from kernel.types import (
124124
BrowserProxy,
125125
BrowserProxyConfig,
126126
BrowserProxyMode,
127+
BrowserReplContent,
128+
BrowserReplImageContent,
129+
BrowserReplRequest,
130+
BrowserReplResult,
131+
BrowserReplTextContent,
127132
BrowserUsage,
128133
Profile,
129134
Tags,
@@ -145,6 +150,7 @@ Methods:
145150
- <code title="post /browsers/{id_or_name}/curl">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">curl</a>(id_or_name, \*\*<a href="src/kernel/types/browser_curl_params.py">params</a>) -> <a href="./src/kernel/types/browser_curl_response.py">BrowserCurlResponse</a></code>
146151
- <code title="delete /browsers/{id_or_name}">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">delete_by_id</a>(id_or_name) -> None</code>
147152
- <code title="post /browsers/{id_or_name}/extensions">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">load_extensions</a>(id_or_name, \*\*<a href="src/kernel/types/browser_load_extensions_params.py">params</a>) -> None</code>
153+
- <code title="post /browsers/{id_or_name}/repl">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">repl</a>(id_or_name, \*\*<a href="src/kernel/types/browser_repl_params.py">params</a>) -> <a href="./src/kernel/types/browser_repl_result.py">BrowserReplResult</a></code>
148154

149155
## Telemetry
150156

‎src/kernel/_client.py‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ def config_registry(self) -> ConfigRegistryResource:
247247

248248
@cached_property
249249
def browsers(self) -> BrowsersResource:
250-
"""Create and manage browser sessions."""
251250
from .resources.browsers import BrowsersResource
252251

253252
return BrowsersResource(self)
@@ -652,7 +651,6 @@ def config_registry(self) -> AsyncConfigRegistryResource:
652651

653652
@cached_property
654653
def browsers(self) -> AsyncBrowsersResource:
655-
"""Create and manage browser sessions."""
656654
from .resources.browsers import AsyncBrowsersResource
657655

658656
return AsyncBrowsersResource(self)
@@ -959,7 +957,6 @@ def config_registry(self) -> config_registry.ConfigRegistryResourceWithRawRespon
959957

960958
@cached_property
961959
def browsers(self) -> browsers.BrowsersResourceWithRawResponse:
962-
"""Create and manage browser sessions."""
963960
from .resources.browsers import BrowsersResourceWithRawResponse
964961

965962
return BrowsersResourceWithRawResponse(self._client.browsers)
@@ -1098,7 +1095,6 @@ def config_registry(self) -> config_registry.AsyncConfigRegistryResourceWithRawR
10981095

10991096
@cached_property
11001097
def browsers(self) -> browsers.AsyncBrowsersResourceWithRawResponse:
1101-
"""Create and manage browser sessions."""
11021098
from .resources.browsers import AsyncBrowsersResourceWithRawResponse
11031099

11041100
return AsyncBrowsersResourceWithRawResponse(self._client.browsers)
@@ -1237,7 +1233,6 @@ def config_registry(self) -> config_registry.ConfigRegistryResourceWithStreaming
12371233

12381234
@cached_property
12391235
def browsers(self) -> browsers.BrowsersResourceWithStreamingResponse:
1240-
"""Create and manage browser sessions."""
12411236
from .resources.browsers import BrowsersResourceWithStreamingResponse
12421237

12431238
return BrowsersResourceWithStreamingResponse(self._client.browsers)
@@ -1376,7 +1371,6 @@ def config_registry(self) -> config_registry.AsyncConfigRegistryResourceWithStre
13761371

13771372
@cached_property
13781373
def browsers(self) -> browsers.AsyncBrowsersResourceWithStreamingResponse:
1379-
"""Create and manage browser sessions."""
13801374
from .resources.browsers import AsyncBrowsersResourceWithStreamingResponse
13811375

13821376
return AsyncBrowsersResourceWithStreamingResponse(self._client.browsers)

‎src/kernel/resources/browsers/browsers.py‎

Lines changed: 148 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
BrowserMemoryRequest,
3737
browser_curl_params,
3838
browser_list_params,
39+
browser_repl_params,
3940
browser_create_params,
4041
browser_update_params,
4142
browser_retrieve_params,
@@ -95,6 +96,7 @@
9596
from ...pagination import SyncOffsetPagination, AsyncOffsetPagination
9697
from ..._base_client import AsyncPaginator, make_request_options
9798
from ...types.tags_param import TagsParam
99+
from ...types.browser_repl_result import BrowserReplResult
98100
from ...types.browser_curl_response import BrowserCurlResponse
99101
from ...types.browser_list_response import BrowserListResponse
100102
from ...types.vault_reference_param import VaultReferenceParam
@@ -118,8 +120,6 @@
118120

119121

120122
class BrowsersResource(SyncAPIResource):
121-
"""Create and manage browser sessions."""
122-
123123
@cached_property
124124
def telemetry(self) -> TelemetryResource:
125125
"""
@@ -753,10 +753,75 @@ def load_extensions(
753753
cast_to=NoneType,
754754
)
755755

756+
def repl(
757+
self,
758+
id_or_name: str,
759+
*,
760+
code: str,
761+
reset: bool | Omit = omit,
762+
timeout_sec: int | Omit = omit,
763+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
764+
# The extra values given here take precedence over values defined on the client or passed to this method.
765+
extra_headers: Headers | None = None,
766+
extra_query: Query | None = None,
767+
extra_body: Body | None = None,
768+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
769+
) -> BrowserReplResult:
770+
"""
771+
Execute JavaScript in a persistent Node.js runtime inside the browser VM.
772+
Top-level bindings, closures, mutations, and dynamically imported modules
773+
persist across calls until the REPL is reset or replaced. Start with
774+
`repl.help()` to list available methods, or call `repl.help("click")` for
775+
detailed help.
776+
777+
Expression values are ignored. Emit ordered text or image output with
778+
`repl.write(...)`, console methods, or `repl.emitImage(...)`. The runtime also
779+
exposes browser-control helpers, WebMCP, Patchright, Playwright, and raw CDP.
780+
781+
Executions are serialized. A timeout, crash, OOM, or protocol failure terminates
782+
the REPL and changes its `repl_id`. This is unrestricted code execution inside
783+
the browser VM and is not sandboxed.
784+
785+
Args:
786+
code: JavaScript evaluated in a persistent Node.js runtime. Top-level bindings persist
787+
until the browser VM's API process exits, the REPL is reset, or the REPL is
788+
terminated after a crash or timeout. Static top-level imports are unsupported;
789+
use dynamic `import()`. Expression values are ignored; emit output with
790+
`repl.write(...)`, console methods, or `repl.emitImage(...)`. May be empty only
791+
when `reset` is true.
792+
793+
reset: Terminate the current REPL, start a fresh one, and then evaluate code.
794+
795+
timeout_sec: Maximum execution time in seconds. Default is 60.
796+
797+
extra_headers: Send extra headers
798+
799+
extra_query: Add additional query parameters to the request
800+
801+
extra_body: Add additional JSON properties to the request
802+
803+
timeout: Override the client-level default timeout for this request, in seconds
804+
"""
805+
if not id_or_name:
806+
raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
807+
return self._post(
808+
path_template("/browsers/{id_or_name}/repl", id_or_name=id_or_name),
809+
body=maybe_transform(
810+
{
811+
"code": code,
812+
"reset": reset,
813+
"timeout_sec": timeout_sec,
814+
},
815+
browser_repl_params.BrowserReplParams,
816+
),
817+
options=make_request_options(
818+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
819+
),
820+
cast_to=BrowserReplResult,
821+
)
756822

757-
class AsyncBrowsersResource(AsyncAPIResource):
758-
"""Create and manage browser sessions."""
759823

824+
class AsyncBrowsersResource(AsyncAPIResource):
760825
@cached_property
761826
def telemetry(self) -> AsyncTelemetryResource:
762827
"""
@@ -1390,6 +1455,73 @@ async def load_extensions(
13901455
cast_to=NoneType,
13911456
)
13921457

1458+
async def repl(
1459+
self,
1460+
id_or_name: str,
1461+
*,
1462+
code: str,
1463+
reset: bool | Omit = omit,
1464+
timeout_sec: int | Omit = omit,
1465+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1466+
# The extra values given here take precedence over values defined on the client or passed to this method.
1467+
extra_headers: Headers | None = None,
1468+
extra_query: Query | None = None,
1469+
extra_body: Body | None = None,
1470+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
1471+
) -> BrowserReplResult:
1472+
"""
1473+
Execute JavaScript in a persistent Node.js runtime inside the browser VM.
1474+
Top-level bindings, closures, mutations, and dynamically imported modules
1475+
persist across calls until the REPL is reset or replaced. Start with
1476+
`repl.help()` to list available methods, or call `repl.help("click")` for
1477+
detailed help.
1478+
1479+
Expression values are ignored. Emit ordered text or image output with
1480+
`repl.write(...)`, console methods, or `repl.emitImage(...)`. The runtime also
1481+
exposes browser-control helpers, WebMCP, Patchright, Playwright, and raw CDP.
1482+
1483+
Executions are serialized. A timeout, crash, OOM, or protocol failure terminates
1484+
the REPL and changes its `repl_id`. This is unrestricted code execution inside
1485+
the browser VM and is not sandboxed.
1486+
1487+
Args:
1488+
code: JavaScript evaluated in a persistent Node.js runtime. Top-level bindings persist
1489+
until the browser VM's API process exits, the REPL is reset, or the REPL is
1490+
terminated after a crash or timeout. Static top-level imports are unsupported;
1491+
use dynamic `import()`. Expression values are ignored; emit output with
1492+
`repl.write(...)`, console methods, or `repl.emitImage(...)`. May be empty only
1493+
when `reset` is true.
1494+
1495+
reset: Terminate the current REPL, start a fresh one, and then evaluate code.
1496+
1497+
timeout_sec: Maximum execution time in seconds. Default is 60.
1498+
1499+
extra_headers: Send extra headers
1500+
1501+
extra_query: Add additional query parameters to the request
1502+
1503+
extra_body: Add additional JSON properties to the request
1504+
1505+
timeout: Override the client-level default timeout for this request, in seconds
1506+
"""
1507+
if not id_or_name:
1508+
raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
1509+
return await self._post(
1510+
path_template("/browsers/{id_or_name}/repl", id_or_name=id_or_name),
1511+
body=await async_maybe_transform(
1512+
{
1513+
"code": code,
1514+
"reset": reset,
1515+
"timeout_sec": timeout_sec,
1516+
},
1517+
browser_repl_params.BrowserReplParams,
1518+
),
1519+
options=make_request_options(
1520+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
1521+
),
1522+
cast_to=BrowserReplResult,
1523+
)
1524+
13931525

13941526
class BrowsersResourceWithRawResponse:
13951527
def __init__(self, browsers: BrowsersResource) -> None:
@@ -1416,6 +1548,9 @@ def __init__(self, browsers: BrowsersResource) -> None:
14161548
self.load_extensions = to_raw_response_wrapper(
14171549
browsers.load_extensions,
14181550
)
1551+
self.repl = to_raw_response_wrapper(
1552+
browsers.repl,
1553+
)
14191554

14201555
@cached_property
14211556
def telemetry(self) -> TelemetryResourceWithRawResponse:
@@ -1485,6 +1620,9 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None:
14851620
self.load_extensions = async_to_raw_response_wrapper(
14861621
browsers.load_extensions,
14871622
)
1623+
self.repl = async_to_raw_response_wrapper(
1624+
browsers.repl,
1625+
)
14881626

14891627
@cached_property
14901628
def telemetry(self) -> AsyncTelemetryResourceWithRawResponse:
@@ -1554,6 +1692,9 @@ def __init__(self, browsers: BrowsersResource) -> None:
15541692
self.load_extensions = to_streamed_response_wrapper(
15551693
browsers.load_extensions,
15561694
)
1695+
self.repl = to_streamed_response_wrapper(
1696+
browsers.repl,
1697+
)
15571698

15581699
@cached_property
15591700
def telemetry(self) -> TelemetryResourceWithStreamingResponse:
@@ -1623,6 +1764,9 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None:
16231764
self.load_extensions = async_to_streamed_response_wrapper(
16241765
browsers.load_extensions,
16251766
)
1767+
self.repl = async_to_streamed_response_wrapper(
1768+
browsers.repl,
1769+
)
16261770

16271771
@cached_property
16281772
def telemetry(self) -> AsyncTelemetryResourceWithStreamingResponse:

‎src/kernel/types/__init__.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
from .api_key_list_params import APIKeyListParams as APIKeyListParams
4949
from .browser_curl_params import BrowserCurlParams as BrowserCurlParams
5050
from .browser_list_params import BrowserListParams as BrowserListParams
51+
from .browser_repl_params import BrowserReplParams as BrowserReplParams
52+
from .browser_repl_result import BrowserReplResult as BrowserReplResult
5153
from .credential_provider import CredentialProvider as CredentialProvider
5254
from .profile_list_params import ProfileListParams as ProfileListParams
5355
from .project_list_params import ProjectListParams as ProjectListParams
@@ -56,6 +58,7 @@
5658
from .proxy_update_params import ProxyUpdateParams as ProxyUpdateParams
5759
from .vault_upsert_params import VaultUpsertParams as VaultUpsertParams
5860
from .browser_proxy_config import BrowserProxyConfig as BrowserProxyConfig
61+
from .browser_repl_content import BrowserReplContent as BrowserReplContent
5962
from .proxy_check_response import ProxyCheckResponse as ProxyCheckResponse
6063
from .api_key_create_params import APIKeyCreateParams as APIKeyCreateParams
6164
from .api_key_rotate_params import APIKeyRotateParams as APIKeyRotateParams
@@ -104,12 +107,14 @@
104107
from .invocation_follow_params import InvocationFollowParams as InvocationFollowParams
105108
from .invocation_list_response import InvocationListResponse as InvocationListResponse
106109
from .invocation_update_params import InvocationUpdateParams as InvocationUpdateParams
110+
from .browser_repl_text_content import BrowserReplTextContent as BrowserReplTextContent
107111
from .browser_retrieve_response import BrowserRetrieveResponse as BrowserRetrieveResponse
108112
from .extension_upload_response import ExtensionUploadResponse as ExtensionUploadResponse
109113
from .browser_pool_create_params import BrowserPoolCreateParams as BrowserPoolCreateParams
110114
from .browser_pool_delete_params import BrowserPoolDeleteParams as BrowserPoolDeleteParams
111115
from .browser_pool_update_params import BrowserPoolUpdateParams as BrowserPoolUpdateParams
112116
from .browser_proxy_config_param import BrowserProxyConfigParam as BrowserProxyConfigParam
117+
from .browser_repl_image_content import BrowserReplImageContent as BrowserReplImageContent
113118
from .deployment_create_response import DeploymentCreateResponse as DeploymentCreateResponse
114119
from .deployment_follow_response import DeploymentFollowResponse as DeploymentFollowResponse
115120
from .invocation_create_response import InvocationCreateResponse as InvocationCreateResponse
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from typing import Union
4+
from typing_extensions import Annotated, TypeAlias
5+
6+
from .._utils import PropertyInfo
7+
from .browser_repl_text_content import BrowserReplTextContent
8+
from .browser_repl_image_content import BrowserReplImageContent
9+
10+
__all__ = ["BrowserReplContent"]
11+
12+
BrowserReplContent: TypeAlias = Annotated[
13+
Union[BrowserReplTextContent, BrowserReplImageContent], PropertyInfo(discriminator="type")
14+
]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from typing_extensions import Literal
4+
5+
from .._models import BaseModel
6+
7+
__all__ = ["BrowserReplImageContent"]
8+
9+
10+
class BrowserReplImageContent(BaseModel):
11+
data_b64: str
12+
13+
mime_type: str
14+
15+
type: Literal["image"]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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 Required, TypedDict
6+
7+
__all__ = ["BrowserReplParams"]
8+
9+
10+
class BrowserReplParams(TypedDict, total=False):
11+
code: Required[str]
12+
"""JavaScript evaluated in a persistent Node.js runtime.
13+
14+
Top-level bindings persist until the browser VM's API process exits, the REPL is
15+
reset, or the REPL is terminated after a crash or timeout. Static top-level
16+
imports are unsupported; use dynamic `import()`. Expression values are ignored;
17+
emit output with `repl.write(...)`, console methods, or `repl.emitImage(...)`.
18+
May be empty only when `reset` is true.
19+
"""
20+
21+
reset: bool
22+
"""Terminate the current REPL, start a fresh one, and then evaluate code."""
23+
24+
timeout_sec: int
25+
"""Maximum execution time in seconds. Default is 60."""

0 commit comments

Comments
 (0)