diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 3d26904f..8f3e0a49 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.14.2"
+ ".": "0.15.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 6bb4af83..b4dc6064 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 57
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6c765f1c4ce1c4dd4ceb371f56bf047aa79af36031ba43cbd68fa16a5fdb9bb3.yml
-openapi_spec_hash: e9086f69281360f4e0895c9274a59531
-config_hash: deadfc4d2b0a947673bcf559b5db6e1b
+configured_endpoints: 64
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e21f0324774a1762bc2bba0da3a8a6b0d0e74720d7a1c83dec813f9e027fcf58.yml
+openapi_spec_hash: f1b636abfd6cb8e7c2ba7ffb8e53b9ba
+config_hash: 09a2df23048cb16689c9a390d9e5bc47
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92e1ed7b..e9fc2228 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 0.15.0 (2025-10-17)
+
+Full Changelog: [v0.14.2...v0.15.0](https://github.com/onkernel/kernel-python-sdk/compare/v0.14.2...v0.15.0)
+
+### Features
+
+* click mouse, move mouse, screenshot ([b63f7ad](https://github.com/onkernel/kernel-python-sdk/commit/b63f7adc7cf0da614a4fc3a9eed491f71f7ec742))
+* Phani/deploy with GitHub url ([eb86c27](https://github.com/onkernel/kernel-python-sdk/commit/eb86c27107781172bf740e0af3833eee86b7cb60))
+
## 0.14.2 (2025-10-16)
Full Changelog: [v0.14.1...v0.14.2](https://github.com/onkernel/kernel-python-sdk/compare/v0.14.1...v0.14.2)
diff --git a/README.md b/README.md
index beec3f01..ae0066ec 100644
--- a/README.md
+++ b/README.md
@@ -218,7 +218,6 @@ from kernel import Kernel
client = Kernel()
client.deployments.create(
- entrypoint_rel_path="src/app.py",
file=Path("/path/to/file"),
)
```
diff --git a/api.md b/api.md
index 6059a78d..858dbfd8 100644
--- a/api.md
+++ b/api.md
@@ -166,6 +166,18 @@ Methods:
- client.browsers.logs.stream(id, \*\*params) -> LogEvent
+## Computer
+
+Methods:
+
+- client.browsers.computer.capture_screenshot(id, \*\*params) -> BinaryAPIResponse
+- client.browsers.computer.click_mouse(id, \*\*params) -> None
+- client.browsers.computer.drag_mouse(id, \*\*params) -> None
+- client.browsers.computer.move_mouse(id, \*\*params) -> None
+- client.browsers.computer.press_key(id, \*\*params) -> None
+- client.browsers.computer.scroll(id, \*\*params) -> None
+- client.browsers.computer.type_text(id, \*\*params) -> None
+
# Profiles
Types:
diff --git a/pyproject.toml b/pyproject.toml
index c2e14c5d..0f8cb140 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "kernel"
-version = "0.14.2"
+version = "0.15.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 dfcce591..e65ca7f2 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.14.2" # x-release-please-version
+__version__ = "0.15.0" # x-release-please-version
diff --git a/src/kernel/resources/browsers/__init__.py b/src/kernel/resources/browsers/__init__.py
index 97c987e4..abcc8f78 100644
--- a/src/kernel/resources/browsers/__init__.py
+++ b/src/kernel/resources/browsers/__init__.py
@@ -40,6 +40,14 @@
BrowsersResourceWithStreamingResponse,
AsyncBrowsersResourceWithStreamingResponse,
)
+from .computer import (
+ ComputerResource,
+ AsyncComputerResource,
+ ComputerResourceWithRawResponse,
+ AsyncComputerResourceWithRawResponse,
+ ComputerResourceWithStreamingResponse,
+ AsyncComputerResourceWithStreamingResponse,
+)
__all__ = [
"ReplaysResource",
@@ -66,6 +74,12 @@
"AsyncLogsResourceWithRawResponse",
"LogsResourceWithStreamingResponse",
"AsyncLogsResourceWithStreamingResponse",
+ "ComputerResource",
+ "AsyncComputerResource",
+ "ComputerResourceWithRawResponse",
+ "AsyncComputerResourceWithRawResponse",
+ "ComputerResourceWithStreamingResponse",
+ "AsyncComputerResourceWithStreamingResponse",
"BrowsersResource",
"AsyncBrowsersResource",
"BrowsersResourceWithRawResponse",
diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py
index 1d444214..c65a738a 100644
--- a/src/kernel/resources/browsers/browsers.py
+++ b/src/kernel/resources/browsers/browsers.py
@@ -41,6 +41,14 @@
)
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .computer import (
+ ComputerResource,
+ AsyncComputerResource,
+ ComputerResourceWithRawResponse,
+ AsyncComputerResourceWithRawResponse,
+ ComputerResourceWithStreamingResponse,
+ AsyncComputerResourceWithStreamingResponse,
+)
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -75,6 +83,10 @@ def process(self) -> ProcessResource:
def logs(self) -> LogsResource:
return LogsResource(self._client)
+ @cached_property
+ def computer(self) -> ComputerResource:
+ return ComputerResource(self._client)
+
@cached_property
def with_raw_response(self) -> BrowsersResourceWithRawResponse:
"""
@@ -375,6 +387,10 @@ def process(self) -> AsyncProcessResource:
def logs(self) -> AsyncLogsResource:
return AsyncLogsResource(self._client)
+ @cached_property
+ def computer(self) -> AsyncComputerResource:
+ return AsyncComputerResource(self._client)
+
@cached_property
def with_raw_response(self) -> AsyncBrowsersResourceWithRawResponse:
"""
@@ -699,6 +715,10 @@ def process(self) -> ProcessResourceWithRawResponse:
def logs(self) -> LogsResourceWithRawResponse:
return LogsResourceWithRawResponse(self._browsers.logs)
+ @cached_property
+ def computer(self) -> ComputerResourceWithRawResponse:
+ return ComputerResourceWithRawResponse(self._browsers.computer)
+
class AsyncBrowsersResourceWithRawResponse:
def __init__(self, browsers: AsyncBrowsersResource) -> None:
@@ -739,6 +759,10 @@ def process(self) -> AsyncProcessResourceWithRawResponse:
def logs(self) -> AsyncLogsResourceWithRawResponse:
return AsyncLogsResourceWithRawResponse(self._browsers.logs)
+ @cached_property
+ def computer(self) -> AsyncComputerResourceWithRawResponse:
+ return AsyncComputerResourceWithRawResponse(self._browsers.computer)
+
class BrowsersResourceWithStreamingResponse:
def __init__(self, browsers: BrowsersResource) -> None:
@@ -779,6 +803,10 @@ def process(self) -> ProcessResourceWithStreamingResponse:
def logs(self) -> LogsResourceWithStreamingResponse:
return LogsResourceWithStreamingResponse(self._browsers.logs)
+ @cached_property
+ def computer(self) -> ComputerResourceWithStreamingResponse:
+ return ComputerResourceWithStreamingResponse(self._browsers.computer)
+
class AsyncBrowsersResourceWithStreamingResponse:
def __init__(self, browsers: AsyncBrowsersResource) -> None:
@@ -818,3 +846,7 @@ def process(self) -> AsyncProcessResourceWithStreamingResponse:
@cached_property
def logs(self) -> AsyncLogsResourceWithStreamingResponse:
return AsyncLogsResourceWithStreamingResponse(self._browsers.logs)
+
+ @cached_property
+ def computer(self) -> AsyncComputerResourceWithStreamingResponse:
+ return AsyncComputerResourceWithStreamingResponse(self._browsers.computer)
diff --git a/src/kernel/resources/browsers/computer.py b/src/kernel/resources/browsers/computer.py
new file mode 100644
index 00000000..68cee420
--- /dev/null
+++ b/src/kernel/resources/browsers/computer.py
@@ -0,0 +1,949 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Literal
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ to_custom_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+ to_custom_streamed_response_wrapper,
+ async_to_custom_raw_response_wrapper,
+ async_to_custom_streamed_response_wrapper,
+)
+from ..._base_client import make_request_options
+from ...types.browsers import (
+ computer_scroll_params,
+ computer_press_key_params,
+ computer_type_text_params,
+ computer_drag_mouse_params,
+ computer_move_mouse_params,
+ computer_click_mouse_params,
+ computer_capture_screenshot_params,
+)
+
+__all__ = ["ComputerResource", "AsyncComputerResource"]
+
+
+class ComputerResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ComputerResourceWithRawResponse:
+ """
+ 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 ComputerResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ComputerResourceWithStreamingResponse:
+ """
+ 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 ComputerResourceWithStreamingResponse(self)
+
+ def capture_screenshot(
+ self,
+ id: str,
+ *,
+ region: computer_capture_screenshot_params.Region | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BinaryAPIResponse:
+ """
+ Capture a screenshot of the browser instance
+
+ 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": "image/png", **(extra_headers or {})}
+ return self._post(
+ f"/browsers/{id}/computer/screenshot",
+ body=maybe_transform(
+ {"region": region}, computer_capture_screenshot_params.ComputerCaptureScreenshotParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BinaryAPIResponse,
+ )
+
+ def click_mouse(
+ self,
+ id: str,
+ *,
+ x: int,
+ y: int,
+ button: Literal["left", "right", "middle", "back", "forward"] | Omit = omit,
+ click_type: Literal["down", "up", "click"] | Omit = omit,
+ hold_keys: SequenceNotStr[str] | Omit = omit,
+ num_clicks: int | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Simulate a mouse click action on the browser instance
+
+ Args:
+ x: X coordinate of the click position
+
+ y: Y coordinate of the click position
+
+ button: Mouse button to interact with
+
+ click_type: Type of click action
+
+ hold_keys: Modifier keys to hold during the click
+
+ num_clicks: Number of times to repeat the click
+
+ 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": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browsers/{id}/computer/click_mouse",
+ body=maybe_transform(
+ {
+ "x": x,
+ "y": y,
+ "button": button,
+ "click_type": click_type,
+ "hold_keys": hold_keys,
+ "num_clicks": num_clicks,
+ },
+ computer_click_mouse_params.ComputerClickMouseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def drag_mouse(
+ self,
+ id: str,
+ *,
+ path: Iterable[Iterable[int]],
+ button: Literal["left", "middle", "right"] | Omit = omit,
+ delay: int | Omit = omit,
+ hold_keys: SequenceNotStr[str] | Omit = omit,
+ step_delay_ms: int | Omit = omit,
+ steps_per_segment: int | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Drag the mouse along a path
+
+ Args:
+ path: Ordered list of [x, y] coordinate pairs to move through while dragging. Must
+ contain at least 2 points.
+
+ button: Mouse button to drag with
+
+ delay: Delay in milliseconds between button down and starting to move along the path.
+
+ hold_keys: Modifier keys to hold during the drag
+
+ step_delay_ms: Delay in milliseconds between relative steps while dragging (not the initial
+ delay).
+
+ steps_per_segment: Number of relative move steps per segment in the path. Minimum 1.
+
+ 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": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browsers/{id}/computer/drag_mouse",
+ body=maybe_transform(
+ {
+ "path": path,
+ "button": button,
+ "delay": delay,
+ "hold_keys": hold_keys,
+ "step_delay_ms": step_delay_ms,
+ "steps_per_segment": steps_per_segment,
+ },
+ computer_drag_mouse_params.ComputerDragMouseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def move_mouse(
+ self,
+ id: str,
+ *,
+ x: int,
+ y: int,
+ hold_keys: SequenceNotStr[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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Move the mouse cursor to the specified coordinates on the browser instance
+
+ Args:
+ x: X coordinate to move the cursor to
+
+ y: Y coordinate to move the cursor to
+
+ hold_keys: Modifier keys to hold during the move
+
+ 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": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browsers/{id}/computer/move_mouse",
+ body=maybe_transform(
+ {
+ "x": x,
+ "y": y,
+ "hold_keys": hold_keys,
+ },
+ computer_move_mouse_params.ComputerMoveMouseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def press_key(
+ self,
+ id: str,
+ *,
+ keys: SequenceNotStr[str],
+ duration: int | Omit = omit,
+ hold_keys: SequenceNotStr[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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Press one or more keys on the host computer
+
+ Args:
+ keys: List of key symbols to press. Each item should be a key symbol supported by
+ xdotool (see X11 keysym definitions). Examples include "Return", "Shift",
+ "Ctrl", "Alt", "F5". Items in this list could also be combinations, e.g.
+ "Ctrl+t" or "Ctrl+Shift+Tab".
+
+ duration: Duration to hold the keys down in milliseconds. If omitted or 0, keys are
+ tapped.
+
+ hold_keys: Optional modifier keys to hold during the key press sequence.
+
+ 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": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browsers/{id}/computer/press_key",
+ body=maybe_transform(
+ {
+ "keys": keys,
+ "duration": duration,
+ "hold_keys": hold_keys,
+ },
+ computer_press_key_params.ComputerPressKeyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def scroll(
+ self,
+ id: str,
+ *,
+ x: int,
+ y: int,
+ delta_x: int | Omit = omit,
+ delta_y: int | Omit = omit,
+ hold_keys: SequenceNotStr[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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Scroll the mouse wheel at a position on the host computer
+
+ Args:
+ x: X coordinate at which to perform the scroll
+
+ y: Y coordinate at which to perform the scroll
+
+ delta_x: Horizontal scroll amount. Positive scrolls right, negative scrolls left.
+
+ delta_y: Vertical scroll amount. Positive scrolls down, negative scrolls up.
+
+ hold_keys: Modifier keys to hold during the scroll
+
+ 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": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browsers/{id}/computer/scroll",
+ body=maybe_transform(
+ {
+ "x": x,
+ "y": y,
+ "delta_x": delta_x,
+ "delta_y": delta_y,
+ "hold_keys": hold_keys,
+ },
+ computer_scroll_params.ComputerScrollParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def type_text(
+ self,
+ id: str,
+ *,
+ text: str,
+ delay: int | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Type text on the browser instance
+
+ Args:
+ text: Text to type on the browser instance
+
+ delay: Delay in milliseconds between keystrokes
+
+ 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": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/browsers/{id}/computer/type",
+ body=maybe_transform(
+ {
+ "text": text,
+ "delay": delay,
+ },
+ computer_type_text_params.ComputerTypeTextParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+
+class AsyncComputerResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncComputerResourceWithRawResponse:
+ """
+ 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 AsyncComputerResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncComputerResourceWithStreamingResponse:
+ """
+ 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 AsyncComputerResourceWithStreamingResponse(self)
+
+ async def capture_screenshot(
+ self,
+ id: str,
+ *,
+ region: computer_capture_screenshot_params.Region | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncBinaryAPIResponse:
+ """
+ Capture a screenshot of the browser instance
+
+ 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": "image/png", **(extra_headers or {})}
+ return await self._post(
+ f"/browsers/{id}/computer/screenshot",
+ body=await async_maybe_transform(
+ {"region": region}, computer_capture_screenshot_params.ComputerCaptureScreenshotParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AsyncBinaryAPIResponse,
+ )
+
+ async def click_mouse(
+ self,
+ id: str,
+ *,
+ x: int,
+ y: int,
+ button: Literal["left", "right", "middle", "back", "forward"] | Omit = omit,
+ click_type: Literal["down", "up", "click"] | Omit = omit,
+ hold_keys: SequenceNotStr[str] | Omit = omit,
+ num_clicks: int | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Simulate a mouse click action on the browser instance
+
+ Args:
+ x: X coordinate of the click position
+
+ y: Y coordinate of the click position
+
+ button: Mouse button to interact with
+
+ click_type: Type of click action
+
+ hold_keys: Modifier keys to hold during the click
+
+ num_clicks: Number of times to repeat the click
+
+ 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": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browsers/{id}/computer/click_mouse",
+ body=await async_maybe_transform(
+ {
+ "x": x,
+ "y": y,
+ "button": button,
+ "click_type": click_type,
+ "hold_keys": hold_keys,
+ "num_clicks": num_clicks,
+ },
+ computer_click_mouse_params.ComputerClickMouseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def drag_mouse(
+ self,
+ id: str,
+ *,
+ path: Iterable[Iterable[int]],
+ button: Literal["left", "middle", "right"] | Omit = omit,
+ delay: int | Omit = omit,
+ hold_keys: SequenceNotStr[str] | Omit = omit,
+ step_delay_ms: int | Omit = omit,
+ steps_per_segment: int | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Drag the mouse along a path
+
+ Args:
+ path: Ordered list of [x, y] coordinate pairs to move through while dragging. Must
+ contain at least 2 points.
+
+ button: Mouse button to drag with
+
+ delay: Delay in milliseconds between button down and starting to move along the path.
+
+ hold_keys: Modifier keys to hold during the drag
+
+ step_delay_ms: Delay in milliseconds between relative steps while dragging (not the initial
+ delay).
+
+ steps_per_segment: Number of relative move steps per segment in the path. Minimum 1.
+
+ 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": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browsers/{id}/computer/drag_mouse",
+ body=await async_maybe_transform(
+ {
+ "path": path,
+ "button": button,
+ "delay": delay,
+ "hold_keys": hold_keys,
+ "step_delay_ms": step_delay_ms,
+ "steps_per_segment": steps_per_segment,
+ },
+ computer_drag_mouse_params.ComputerDragMouseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def move_mouse(
+ self,
+ id: str,
+ *,
+ x: int,
+ y: int,
+ hold_keys: SequenceNotStr[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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Move the mouse cursor to the specified coordinates on the browser instance
+
+ Args:
+ x: X coordinate to move the cursor to
+
+ y: Y coordinate to move the cursor to
+
+ hold_keys: Modifier keys to hold during the move
+
+ 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": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browsers/{id}/computer/move_mouse",
+ body=await async_maybe_transform(
+ {
+ "x": x,
+ "y": y,
+ "hold_keys": hold_keys,
+ },
+ computer_move_mouse_params.ComputerMoveMouseParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def press_key(
+ self,
+ id: str,
+ *,
+ keys: SequenceNotStr[str],
+ duration: int | Omit = omit,
+ hold_keys: SequenceNotStr[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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Press one or more keys on the host computer
+
+ Args:
+ keys: List of key symbols to press. Each item should be a key symbol supported by
+ xdotool (see X11 keysym definitions). Examples include "Return", "Shift",
+ "Ctrl", "Alt", "F5". Items in this list could also be combinations, e.g.
+ "Ctrl+t" or "Ctrl+Shift+Tab".
+
+ duration: Duration to hold the keys down in milliseconds. If omitted or 0, keys are
+ tapped.
+
+ hold_keys: Optional modifier keys to hold during the key press sequence.
+
+ 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": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browsers/{id}/computer/press_key",
+ body=await async_maybe_transform(
+ {
+ "keys": keys,
+ "duration": duration,
+ "hold_keys": hold_keys,
+ },
+ computer_press_key_params.ComputerPressKeyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def scroll(
+ self,
+ id: str,
+ *,
+ x: int,
+ y: int,
+ delta_x: int | Omit = omit,
+ delta_y: int | Omit = omit,
+ hold_keys: SequenceNotStr[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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Scroll the mouse wheel at a position on the host computer
+
+ Args:
+ x: X coordinate at which to perform the scroll
+
+ y: Y coordinate at which to perform the scroll
+
+ delta_x: Horizontal scroll amount. Positive scrolls right, negative scrolls left.
+
+ delta_y: Vertical scroll amount. Positive scrolls down, negative scrolls up.
+
+ hold_keys: Modifier keys to hold during the scroll
+
+ 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": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browsers/{id}/computer/scroll",
+ body=await async_maybe_transform(
+ {
+ "x": x,
+ "y": y,
+ "delta_x": delta_x,
+ "delta_y": delta_y,
+ "hold_keys": hold_keys,
+ },
+ computer_scroll_params.ComputerScrollParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def type_text(
+ self,
+ id: str,
+ *,
+ text: str,
+ delay: int | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Type text on the browser instance
+
+ Args:
+ text: Text to type on the browser instance
+
+ delay: Delay in milliseconds between keystrokes
+
+ 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": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/browsers/{id}/computer/type",
+ body=await async_maybe_transform(
+ {
+ "text": text,
+ "delay": delay,
+ },
+ computer_type_text_params.ComputerTypeTextParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+
+class ComputerResourceWithRawResponse:
+ def __init__(self, computer: ComputerResource) -> None:
+ self._computer = computer
+
+ self.capture_screenshot = to_custom_raw_response_wrapper(
+ computer.capture_screenshot,
+ BinaryAPIResponse,
+ )
+ self.click_mouse = to_raw_response_wrapper(
+ computer.click_mouse,
+ )
+ self.drag_mouse = to_raw_response_wrapper(
+ computer.drag_mouse,
+ )
+ self.move_mouse = to_raw_response_wrapper(
+ computer.move_mouse,
+ )
+ self.press_key = to_raw_response_wrapper(
+ computer.press_key,
+ )
+ self.scroll = to_raw_response_wrapper(
+ computer.scroll,
+ )
+ self.type_text = to_raw_response_wrapper(
+ computer.type_text,
+ )
+
+
+class AsyncComputerResourceWithRawResponse:
+ def __init__(self, computer: AsyncComputerResource) -> None:
+ self._computer = computer
+
+ self.capture_screenshot = async_to_custom_raw_response_wrapper(
+ computer.capture_screenshot,
+ AsyncBinaryAPIResponse,
+ )
+ self.click_mouse = async_to_raw_response_wrapper(
+ computer.click_mouse,
+ )
+ self.drag_mouse = async_to_raw_response_wrapper(
+ computer.drag_mouse,
+ )
+ self.move_mouse = async_to_raw_response_wrapper(
+ computer.move_mouse,
+ )
+ self.press_key = async_to_raw_response_wrapper(
+ computer.press_key,
+ )
+ self.scroll = async_to_raw_response_wrapper(
+ computer.scroll,
+ )
+ self.type_text = async_to_raw_response_wrapper(
+ computer.type_text,
+ )
+
+
+class ComputerResourceWithStreamingResponse:
+ def __init__(self, computer: ComputerResource) -> None:
+ self._computer = computer
+
+ self.capture_screenshot = to_custom_streamed_response_wrapper(
+ computer.capture_screenshot,
+ StreamedBinaryAPIResponse,
+ )
+ self.click_mouse = to_streamed_response_wrapper(
+ computer.click_mouse,
+ )
+ self.drag_mouse = to_streamed_response_wrapper(
+ computer.drag_mouse,
+ )
+ self.move_mouse = to_streamed_response_wrapper(
+ computer.move_mouse,
+ )
+ self.press_key = to_streamed_response_wrapper(
+ computer.press_key,
+ )
+ self.scroll = to_streamed_response_wrapper(
+ computer.scroll,
+ )
+ self.type_text = to_streamed_response_wrapper(
+ computer.type_text,
+ )
+
+
+class AsyncComputerResourceWithStreamingResponse:
+ def __init__(self, computer: AsyncComputerResource) -> None:
+ self._computer = computer
+
+ self.capture_screenshot = async_to_custom_streamed_response_wrapper(
+ computer.capture_screenshot,
+ AsyncStreamedBinaryAPIResponse,
+ )
+ self.click_mouse = async_to_streamed_response_wrapper(
+ computer.click_mouse,
+ )
+ self.drag_mouse = async_to_streamed_response_wrapper(
+ computer.drag_mouse,
+ )
+ self.move_mouse = async_to_streamed_response_wrapper(
+ computer.move_mouse,
+ )
+ self.press_key = async_to_streamed_response_wrapper(
+ computer.press_key,
+ )
+ self.scroll = async_to_streamed_response_wrapper(
+ computer.scroll,
+ )
+ self.type_text = async_to_streamed_response_wrapper(
+ computer.type_text,
+ )
diff --git a/src/kernel/resources/deployments.py b/src/kernel/resources/deployments.py
index 15812440..bdc200f1 100644
--- a/src/kernel/resources/deployments.py
+++ b/src/kernel/resources/deployments.py
@@ -52,11 +52,12 @@ def with_streaming_response(self) -> DeploymentsResourceWithStreamingResponse:
def create(
self,
*,
- entrypoint_rel_path: str,
- file: FileTypes,
+ entrypoint_rel_path: str | Omit = omit,
env_vars: Dict[str, str] | Omit = omit,
+ file: FileTypes | Omit = omit,
force: bool | Omit = omit,
region: Literal["aws.us-east-1a"] | Omit = omit,
+ source: deployment_create_params.Source | Omit = omit,
version: 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.
@@ -71,15 +72,17 @@ def create(
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.
+ file: ZIP file containing the application source directory
+
force: Allow overwriting an existing app version
region: Region for deployment. Currently we only support "aws.us-east-1a"
+ source: Source from which to fetch application code.
+
version: Version of the application. Can be any string.
extra_headers: Send extra headers
@@ -93,10 +96,11 @@ def create(
body = deepcopy_minimal(
{
"entrypoint_rel_path": entrypoint_rel_path,
- "file": file,
"env_vars": env_vars,
+ "file": file,
"force": force,
"region": region,
+ "source": source,
"version": version,
}
)
@@ -271,11 +275,12 @@ def with_streaming_response(self) -> AsyncDeploymentsResourceWithStreamingRespon
async def create(
self,
*,
- entrypoint_rel_path: str,
- file: FileTypes,
+ entrypoint_rel_path: str | Omit = omit,
env_vars: Dict[str, str] | Omit = omit,
+ file: FileTypes | Omit = omit,
force: bool | Omit = omit,
region: Literal["aws.us-east-1a"] | Omit = omit,
+ source: deployment_create_params.Source | Omit = omit,
version: 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.
@@ -290,15 +295,17 @@ async def create(
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.
+ file: ZIP file containing the application source directory
+
force: Allow overwriting an existing app version
region: Region for deployment. Currently we only support "aws.us-east-1a"
+ source: Source from which to fetch application code.
+
version: Version of the application. Can be any string.
extra_headers: Send extra headers
@@ -312,10 +319,11 @@ async def create(
body = deepcopy_minimal(
{
"entrypoint_rel_path": entrypoint_rel_path,
- "file": file,
"env_vars": env_vars,
+ "file": file,
"force": force,
"region": region,
+ "source": source,
"version": version,
}
)
diff --git a/src/kernel/types/browsers/__init__.py b/src/kernel/types/browsers/__init__.py
index d0b6b383..9b0ed53a 100644
--- a/src/kernel/types/browsers/__init__.py
+++ b/src/kernel/types/browsers/__init__.py
@@ -22,11 +22,18 @@
from .process_exec_response import ProcessExecResponse as ProcessExecResponse
from .process_kill_response import ProcessKillResponse as ProcessKillResponse
from .replay_start_response import ReplayStartResponse as ReplayStartResponse
+from .computer_scroll_params import ComputerScrollParams as ComputerScrollParams
from .process_spawn_response import ProcessSpawnResponse as ProcessSpawnResponse
from .process_stdin_response import ProcessStdinResponse as ProcessStdinResponse
from .process_status_response import ProcessStatusResponse as ProcessStatusResponse
+from .computer_press_key_params import ComputerPressKeyParams as ComputerPressKeyParams
+from .computer_type_text_params import ComputerTypeTextParams as ComputerTypeTextParams
from .f_create_directory_params import FCreateDirectoryParams as FCreateDirectoryParams
from .f_delete_directory_params import FDeleteDirectoryParams as FDeleteDirectoryParams
from .f_download_dir_zip_params import FDownloadDirZipParams as FDownloadDirZipParams
+from .computer_drag_mouse_params import ComputerDragMouseParams as ComputerDragMouseParams
+from .computer_move_mouse_params import ComputerMoveMouseParams as ComputerMoveMouseParams
+from .computer_click_mouse_params import ComputerClickMouseParams as ComputerClickMouseParams
from .f_set_file_permissions_params import FSetFilePermissionsParams as FSetFilePermissionsParams
from .process_stdout_stream_response import ProcessStdoutStreamResponse as ProcessStdoutStreamResponse
+from .computer_capture_screenshot_params import ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams
diff --git a/src/kernel/types/browsers/computer_capture_screenshot_params.py b/src/kernel/types/browsers/computer_capture_screenshot_params.py
new file mode 100644
index 00000000..942cef30
--- /dev/null
+++ b/src/kernel/types/browsers/computer_capture_screenshot_params.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ComputerCaptureScreenshotParams", "Region"]
+
+
+class ComputerCaptureScreenshotParams(TypedDict, total=False):
+ region: Region
+
+
+class Region(TypedDict, total=False):
+ height: Required[int]
+ """Height of the region in pixels"""
+
+ width: Required[int]
+ """Width of the region in pixels"""
+
+ x: Required[int]
+ """X coordinate of the region's top-left corner"""
+
+ y: Required[int]
+ """Y coordinate of the region's top-left corner"""
diff --git a/src/kernel/types/browsers/computer_click_mouse_params.py b/src/kernel/types/browsers/computer_click_mouse_params.py
new file mode 100644
index 00000000..9bde2e6a
--- /dev/null
+++ b/src/kernel/types/browsers/computer_click_mouse_params.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from ..._types import SequenceNotStr
+
+__all__ = ["ComputerClickMouseParams"]
+
+
+class ComputerClickMouseParams(TypedDict, total=False):
+ x: Required[int]
+ """X coordinate of the click position"""
+
+ y: Required[int]
+ """Y coordinate of the click position"""
+
+ button: Literal["left", "right", "middle", "back", "forward"]
+ """Mouse button to interact with"""
+
+ click_type: Literal["down", "up", "click"]
+ """Type of click action"""
+
+ hold_keys: SequenceNotStr[str]
+ """Modifier keys to hold during the click"""
+
+ num_clicks: int
+ """Number of times to repeat the click"""
diff --git a/src/kernel/types/browsers/computer_drag_mouse_params.py b/src/kernel/types/browsers/computer_drag_mouse_params.py
new file mode 100644
index 00000000..fb03b4be
--- /dev/null
+++ b/src/kernel/types/browsers/computer_drag_mouse_params.py
@@ -0,0 +1,36 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Literal, Required, TypedDict
+
+from ..._types import SequenceNotStr
+
+__all__ = ["ComputerDragMouseParams"]
+
+
+class ComputerDragMouseParams(TypedDict, total=False):
+ path: Required[Iterable[Iterable[int]]]
+ """Ordered list of [x, y] coordinate pairs to move through while dragging.
+
+ Must contain at least 2 points.
+ """
+
+ button: Literal["left", "middle", "right"]
+ """Mouse button to drag with"""
+
+ delay: int
+ """Delay in milliseconds between button down and starting to move along the path."""
+
+ hold_keys: SequenceNotStr[str]
+ """Modifier keys to hold during the drag"""
+
+ step_delay_ms: int
+ """
+ Delay in milliseconds between relative steps while dragging (not the initial
+ delay).
+ """
+
+ steps_per_segment: int
+ """Number of relative move steps per segment in the path. Minimum 1."""
diff --git a/src/kernel/types/browsers/computer_move_mouse_params.py b/src/kernel/types/browsers/computer_move_mouse_params.py
new file mode 100644
index 00000000..1769e074
--- /dev/null
+++ b/src/kernel/types/browsers/computer_move_mouse_params.py
@@ -0,0 +1,20 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from ..._types import SequenceNotStr
+
+__all__ = ["ComputerMoveMouseParams"]
+
+
+class ComputerMoveMouseParams(TypedDict, total=False):
+ x: Required[int]
+ """X coordinate to move the cursor to"""
+
+ y: Required[int]
+ """Y coordinate to move the cursor to"""
+
+ hold_keys: SequenceNotStr[str]
+ """Modifier keys to hold during the move"""
diff --git a/src/kernel/types/browsers/computer_press_key_params.py b/src/kernel/types/browsers/computer_press_key_params.py
new file mode 100644
index 00000000..ea2c9b45
--- /dev/null
+++ b/src/kernel/types/browsers/computer_press_key_params.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from ..._types import SequenceNotStr
+
+__all__ = ["ComputerPressKeyParams"]
+
+
+class ComputerPressKeyParams(TypedDict, total=False):
+ keys: Required[SequenceNotStr[str]]
+ """List of key symbols to press.
+
+ Each item should be a key symbol supported by xdotool (see X11 keysym
+ definitions). Examples include "Return", "Shift", "Ctrl", "Alt", "F5". Items in
+ this list could also be combinations, e.g. "Ctrl+t" or "Ctrl+Shift+Tab".
+ """
+
+ duration: int
+ """Duration to hold the keys down in milliseconds.
+
+ If omitted or 0, keys are tapped.
+ """
+
+ hold_keys: SequenceNotStr[str]
+ """Optional modifier keys to hold during the key press sequence."""
diff --git a/src/kernel/types/browsers/computer_scroll_params.py b/src/kernel/types/browsers/computer_scroll_params.py
new file mode 100644
index 00000000..110cb302
--- /dev/null
+++ b/src/kernel/types/browsers/computer_scroll_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from ..._types import SequenceNotStr
+
+__all__ = ["ComputerScrollParams"]
+
+
+class ComputerScrollParams(TypedDict, total=False):
+ x: Required[int]
+ """X coordinate at which to perform the scroll"""
+
+ y: Required[int]
+ """Y coordinate at which to perform the scroll"""
+
+ delta_x: int
+ """Horizontal scroll amount. Positive scrolls right, negative scrolls left."""
+
+ delta_y: int
+ """Vertical scroll amount. Positive scrolls down, negative scrolls up."""
+
+ hold_keys: SequenceNotStr[str]
+ """Modifier keys to hold during the scroll"""
diff --git a/src/kernel/types/browsers/computer_type_text_params.py b/src/kernel/types/browsers/computer_type_text_params.py
new file mode 100644
index 00000000..3a2c5133
--- /dev/null
+++ b/src/kernel/types/browsers/computer_type_text_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ComputerTypeTextParams"]
+
+
+class ComputerTypeTextParams(TypedDict, total=False):
+ text: Required[str]
+ """Text to type on the browser instance"""
+
+ delay: int
+ """Delay in milliseconds between keystrokes"""
diff --git a/src/kernel/types/deployment_create_params.py b/src/kernel/types/deployment_create_params.py
index 6701c0a8..16eb5702 100644
--- a/src/kernel/types/deployment_create_params.py
+++ b/src/kernel/types/deployment_create_params.py
@@ -7,27 +7,58 @@
from .._types import FileTypes
-__all__ = ["DeploymentCreateParams"]
+__all__ = ["DeploymentCreateParams", "Source", "SourceAuth"]
class DeploymentCreateParams(TypedDict, total=False):
- entrypoint_rel_path: Required[str]
+ entrypoint_rel_path: 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.
"""
+ file: FileTypes
+ """ZIP file containing the application source directory"""
+
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" """
+ source: Source
+ """Source from which to fetch application code."""
+
version: str
"""Version of the application. Can be any string."""
+
+
+class SourceAuth(TypedDict, total=False):
+ token: Required[str]
+ """GitHub PAT or installation access token"""
+
+ method: Required[Literal["github_token"]]
+ """Auth method"""
+
+
+class Source(TypedDict, total=False):
+ entrypoint: Required[str]
+ """Relative path to the application entrypoint within the selected path."""
+
+ ref: Required[str]
+ """Git ref (branch, tag, or commit SHA) to fetch."""
+
+ type: Required[Literal["github"]]
+ """Source type identifier."""
+
+ url: Required[str]
+ """Base repository URL (without blob/tree suffixes)."""
+
+ auth: SourceAuth
+ """Authentication for private repositories."""
+
+ path: str
+ """Path within the repo to deploy (omit to use repo root)."""
diff --git a/tests/api_resources/browsers/test_computer.py b/tests/api_resources/browsers/test_computer.py
new file mode 100644
index 00000000..9e245481
--- /dev/null
+++ b/tests/api_resources/browsers/test_computer.py
@@ -0,0 +1,892 @@
+# 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 httpx
+import pytest
+from respx import MockRouter
+
+from kernel import Kernel, AsyncKernel
+from kernel._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestComputer:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_capture_screenshot(self, client: Kernel, respx_mock: MockRouter) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ computer = client.browsers.computer.capture_screenshot(
+ id="id",
+ )
+ assert computer.is_closed
+ assert computer.json() == {"foo": "bar"}
+ assert cast(Any, computer.is_closed) is True
+ assert isinstance(computer, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_capture_screenshot_with_all_params(self, client: Kernel, respx_mock: MockRouter) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ computer = client.browsers.computer.capture_screenshot(
+ id="id",
+ region={
+ "height": 0,
+ "width": 0,
+ "x": 0,
+ "y": 0,
+ },
+ )
+ assert computer.is_closed
+ assert computer.json() == {"foo": "bar"}
+ assert cast(Any, computer.is_closed) is True
+ assert isinstance(computer, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_raw_response_capture_screenshot(self, client: Kernel, respx_mock: MockRouter) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+
+ computer = client.browsers.computer.with_raw_response.capture_screenshot(
+ id="id",
+ )
+
+ assert computer.is_closed is True
+ assert computer.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert computer.json() == {"foo": "bar"}
+ assert isinstance(computer, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_streaming_response_capture_screenshot(self, client: Kernel, respx_mock: MockRouter) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ with client.browsers.computer.with_streaming_response.capture_screenshot(
+ id="id",
+ ) as computer:
+ assert not computer.is_closed
+ assert computer.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert computer.json() == {"foo": "bar"}
+ assert cast(Any, computer.is_closed) is True
+ assert isinstance(computer, StreamedBinaryAPIResponse)
+
+ assert cast(Any, computer.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_path_params_capture_screenshot(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.browsers.computer.with_raw_response.capture_screenshot(
+ id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_click_mouse(self, client: Kernel) -> None:
+ computer = client.browsers.computer.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_click_mouse_with_all_params(self, client: Kernel) -> None:
+ computer = client.browsers.computer.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ button="left",
+ click_type="down",
+ hold_keys=["string"],
+ num_clicks=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_click_mouse(self, client: Kernel) -> None:
+ response = client.browsers.computer.with_raw_response.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_click_mouse(self, client: Kernel) -> None:
+ with client.browsers.computer.with_streaming_response.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_click_mouse(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.browsers.computer.with_raw_response.click_mouse(
+ id="",
+ x=0,
+ y=0,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_drag_mouse(self, client: Kernel) -> None:
+ computer = client.browsers.computer.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_drag_mouse_with_all_params(self, client: Kernel) -> None:
+ computer = client.browsers.computer.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ button="left",
+ delay=0,
+ hold_keys=["string"],
+ step_delay_ms=0,
+ steps_per_segment=1,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_drag_mouse(self, client: Kernel) -> None:
+ response = client.browsers.computer.with_raw_response.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_drag_mouse(self, client: Kernel) -> None:
+ with client.browsers.computer.with_streaming_response.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_drag_mouse(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.browsers.computer.with_raw_response.drag_mouse(
+ id="",
+ path=[[0, 0], [0, 0]],
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_move_mouse(self, client: Kernel) -> None:
+ computer = client.browsers.computer.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_move_mouse_with_all_params(self, client: Kernel) -> None:
+ computer = client.browsers.computer.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ hold_keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_move_mouse(self, client: Kernel) -> None:
+ response = client.browsers.computer.with_raw_response.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_move_mouse(self, client: Kernel) -> None:
+ with client.browsers.computer.with_streaming_response.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_move_mouse(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.browsers.computer.with_raw_response.move_mouse(
+ id="",
+ x=0,
+ y=0,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_press_key(self, client: Kernel) -> None:
+ computer = client.browsers.computer.press_key(
+ id="id",
+ keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_press_key_with_all_params(self, client: Kernel) -> None:
+ computer = client.browsers.computer.press_key(
+ id="id",
+ keys=["string"],
+ duration=0,
+ hold_keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_press_key(self, client: Kernel) -> None:
+ response = client.browsers.computer.with_raw_response.press_key(
+ id="id",
+ keys=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_press_key(self, client: Kernel) -> None:
+ with client.browsers.computer.with_streaming_response.press_key(
+ id="id",
+ keys=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_press_key(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.browsers.computer.with_raw_response.press_key(
+ id="",
+ keys=["string"],
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_scroll(self, client: Kernel) -> None:
+ computer = client.browsers.computer.scroll(
+ id="id",
+ x=0,
+ y=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_scroll_with_all_params(self, client: Kernel) -> None:
+ computer = client.browsers.computer.scroll(
+ id="id",
+ x=0,
+ y=0,
+ delta_x=0,
+ delta_y=0,
+ hold_keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_scroll(self, client: Kernel) -> None:
+ response = client.browsers.computer.with_raw_response.scroll(
+ id="id",
+ x=0,
+ y=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_scroll(self, client: Kernel) -> None:
+ with client.browsers.computer.with_streaming_response.scroll(
+ id="id",
+ x=0,
+ y=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_scroll(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.browsers.computer.with_raw_response.scroll(
+ id="",
+ x=0,
+ y=0,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_type_text(self, client: Kernel) -> None:
+ computer = client.browsers.computer.type_text(
+ id="id",
+ text="text",
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_type_text_with_all_params(self, client: Kernel) -> None:
+ computer = client.browsers.computer.type_text(
+ id="id",
+ text="text",
+ delay=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_type_text(self, client: Kernel) -> None:
+ response = client.browsers.computer.with_raw_response.type_text(
+ id="id",
+ text="text",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_type_text(self, client: Kernel) -> None:
+ with client.browsers.computer.with_streaming_response.type_text(
+ id="id",
+ text="text",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_type_text(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.browsers.computer.with_raw_response.type_text(
+ id="",
+ text="text",
+ )
+
+
+class TestAsyncComputer:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_capture_screenshot(self, async_client: AsyncKernel, respx_mock: MockRouter) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ computer = await async_client.browsers.computer.capture_screenshot(
+ id="id",
+ )
+ assert computer.is_closed
+ assert await computer.json() == {"foo": "bar"}
+ assert cast(Any, computer.is_closed) is True
+ assert isinstance(computer, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_capture_screenshot_with_all_params(
+ self, async_client: AsyncKernel, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ computer = await async_client.browsers.computer.capture_screenshot(
+ id="id",
+ region={
+ "height": 0,
+ "width": 0,
+ "x": 0,
+ "y": 0,
+ },
+ )
+ assert computer.is_closed
+ assert await computer.json() == {"foo": "bar"}
+ assert cast(Any, computer.is_closed) is True
+ assert isinstance(computer, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_raw_response_capture_screenshot(self, async_client: AsyncKernel, respx_mock: MockRouter) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+
+ computer = await async_client.browsers.computer.with_raw_response.capture_screenshot(
+ id="id",
+ )
+
+ assert computer.is_closed is True
+ assert computer.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert await computer.json() == {"foo": "bar"}
+ assert isinstance(computer, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_streaming_response_capture_screenshot(
+ self, async_client: AsyncKernel, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.post("/browsers/id/computer/screenshot").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ async with async_client.browsers.computer.with_streaming_response.capture_screenshot(
+ id="id",
+ ) as computer:
+ assert not computer.is_closed
+ assert computer.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert await computer.json() == {"foo": "bar"}
+ assert cast(Any, computer.is_closed) is True
+ assert isinstance(computer, AsyncStreamedBinaryAPIResponse)
+
+ assert cast(Any, computer.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_path_params_capture_screenshot(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.browsers.computer.with_raw_response.capture_screenshot(
+ id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_click_mouse(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_click_mouse_with_all_params(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ button="left",
+ click_type="down",
+ hold_keys=["string"],
+ num_clicks=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_click_mouse(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browsers.computer.with_raw_response.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_click_mouse(self, async_client: AsyncKernel) -> None:
+ async with async_client.browsers.computer.with_streaming_response.click_mouse(
+ id="id",
+ x=0,
+ y=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_click_mouse(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.browsers.computer.with_raw_response.click_mouse(
+ id="",
+ x=0,
+ y=0,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_drag_mouse(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_drag_mouse_with_all_params(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ button="left",
+ delay=0,
+ hold_keys=["string"],
+ step_delay_ms=0,
+ steps_per_segment=1,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_drag_mouse(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browsers.computer.with_raw_response.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_drag_mouse(self, async_client: AsyncKernel) -> None:
+ async with async_client.browsers.computer.with_streaming_response.drag_mouse(
+ id="id",
+ path=[[0, 0], [0, 0]],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_drag_mouse(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.browsers.computer.with_raw_response.drag_mouse(
+ id="",
+ path=[[0, 0], [0, 0]],
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_move_mouse(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_move_mouse_with_all_params(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ hold_keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_move_mouse(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browsers.computer.with_raw_response.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_move_mouse(self, async_client: AsyncKernel) -> None:
+ async with async_client.browsers.computer.with_streaming_response.move_mouse(
+ id="id",
+ x=0,
+ y=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_move_mouse(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.browsers.computer.with_raw_response.move_mouse(
+ id="",
+ x=0,
+ y=0,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_press_key(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.press_key(
+ id="id",
+ keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_press_key_with_all_params(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.press_key(
+ id="id",
+ keys=["string"],
+ duration=0,
+ hold_keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_press_key(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browsers.computer.with_raw_response.press_key(
+ id="id",
+ keys=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_press_key(self, async_client: AsyncKernel) -> None:
+ async with async_client.browsers.computer.with_streaming_response.press_key(
+ id="id",
+ keys=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_press_key(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.browsers.computer.with_raw_response.press_key(
+ id="",
+ keys=["string"],
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_scroll(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.scroll(
+ id="id",
+ x=0,
+ y=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_scroll_with_all_params(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.scroll(
+ id="id",
+ x=0,
+ y=0,
+ delta_x=0,
+ delta_y=0,
+ hold_keys=["string"],
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_scroll(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browsers.computer.with_raw_response.scroll(
+ id="id",
+ x=0,
+ y=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_scroll(self, async_client: AsyncKernel) -> None:
+ async with async_client.browsers.computer.with_streaming_response.scroll(
+ id="id",
+ x=0,
+ y=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_scroll(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.browsers.computer.with_raw_response.scroll(
+ id="",
+ x=0,
+ y=0,
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_type_text(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.type_text(
+ id="id",
+ text="text",
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_type_text_with_all_params(self, async_client: AsyncKernel) -> None:
+ computer = await async_client.browsers.computer.type_text(
+ id="id",
+ text="text",
+ delay=0,
+ )
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_type_text(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browsers.computer.with_raw_response.type_text(
+ id="id",
+ text="text",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert computer is None
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_type_text(self, async_client: AsyncKernel) -> None:
+ async with async_client.browsers.computer.with_streaming_response.type_text(
+ id="id",
+ text="text",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert computer is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_type_text(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.browsers.computer.with_raw_response.type_text(
+ id="",
+ text="text",
+ )
diff --git a/tests/api_resources/test_deployments.py b/tests/api_resources/test_deployments.py
index fc5d2991..6c3354ef 100644
--- a/tests/api_resources/test_deployments.py
+++ b/tests/api_resources/test_deployments.py
@@ -25,10 +25,7 @@ class TestDeployments:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_create(self, client: Kernel) -> None:
- deployment = client.deployments.create(
- entrypoint_rel_path="src/app.py",
- file=b"raw file contents",
- )
+ deployment = client.deployments.create()
assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@@ -36,10 +33,21 @@ def test_method_create(self, client: Kernel) -> None:
def test_method_create_with_all_params(self, client: Kernel) -> None:
deployment = client.deployments.create(
entrypoint_rel_path="src/app.py",
+ env_vars={"FOO": "bar"},
file=b"raw file contents",
- env_vars={"foo": "string"},
force=False,
region="aws.us-east-1a",
+ source={
+ "entrypoint": "src/index.ts",
+ "ref": "main",
+ "type": "github",
+ "url": "https://github.com/org/repo",
+ "auth": {
+ "token": "ghs_***",
+ "method": "github_token",
+ },
+ "path": "apps/api",
+ },
version="1.0.0",
)
assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
@@ -47,10 +55,7 @@ def test_method_create_with_all_params(self, client: Kernel) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@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",
- )
+ response = client.deployments.with_raw_response.create()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -60,10 +65,7 @@ def test_raw_response_create(self, client: Kernel) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@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:
+ with client.deployments.with_streaming_response.create() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -211,10 +213,7 @@ class TestAsyncDeployments:
@pytest.mark.skip(reason="Prism tests are disabled")
@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",
- )
+ deployment = await async_client.deployments.create()
assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@@ -222,10 +221,21 @@ async def test_method_create(self, async_client: AsyncKernel) -> None:
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",
+ env_vars={"FOO": "bar"},
file=b"raw file contents",
- env_vars={"foo": "string"},
force=False,
region="aws.us-east-1a",
+ source={
+ "entrypoint": "src/index.ts",
+ "ref": "main",
+ "type": "github",
+ "url": "https://github.com/org/repo",
+ "auth": {
+ "token": "ghs_***",
+ "method": "github_token",
+ },
+ "path": "apps/api",
+ },
version="1.0.0",
)
assert_matches_type(DeploymentCreateResponse, deployment, path=["response"])
@@ -233,10 +243,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) ->
@pytest.mark.skip(reason="Prism tests are disabled")
@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",
- )
+ response = await async_client.deployments.with_raw_response.create()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -246,10 +253,7 @@ async def test_raw_response_create(self, async_client: AsyncKernel) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@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:
+ async with async_client.deployments.with_streaming_response.create() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"