diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 40293964..c8a8a4f7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,7 +12,6 @@ jobs:
lint:
name: lint
runs-on: ubuntu-latest
-
steps:
- uses: actions/checkout@v4
@@ -30,6 +29,7 @@ jobs:
- name: Run lints
run: ./scripts/lint
+
test:
name: test
runs-on: ubuntu-latest
@@ -50,4 +50,3 @@ jobs:
- name: Run tests
run: ./scripts/test
-
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 8f3e0a49..b4e9013b 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.15.0"
+ ".": "0.16.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 45bcc813..c981a627 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
-configured_endpoints: 61
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-2d76871c6215358c176295dc168fa7f571f81df1f8df37ecbd1e4e06e7220d67.yml
+configured_endpoints: 66
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-5d84d2732400f196ddbe4b4e7c0e98b3f02bab9ce2ed750e69d399d898e496d1.yml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7949b852..e1cf569d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## 0.16.0 (2025-01-31)
+
+Full Changelog: [v0.15.0...v0.16.0](https://github.com/runloopai/api-client-python/compare/v0.15.0...v0.16.0)
+
+### Features
+
+* **api:** api update ([#510](https://github.com/runloopai/api-client-python/issues/510)) ([914ee46](https://github.com/runloopai/api-client-python/commit/914ee460ccdc6bbd58a7a263d5566716b4bbf9df))
+
+
+### Chores
+
+* **internal:** codegen related update ([#508](https://github.com/runloopai/api-client-python/issues/508)) ([278e736](https://github.com/runloopai/api-client-python/commit/278e736787b66e0d0a5fbc64743a386cfefd1994))
+
## 0.15.0 (2025-01-29)
Full Changelog: [v0.14.0...v0.15.0](https://github.com/runloopai/api-client-python/compare/v0.14.0...v0.15.0)
diff --git a/api.md b/api.md
index 46135d10..8967b08e 100644
--- a/api.md
+++ b/api.md
@@ -100,6 +100,38 @@ Methods:
- client.devboxes.upload_file(id, \*\*params) -> object
- client.devboxes.write_file_contents(id, \*\*params) -> DevboxExecutionDetailView
+## Browsers
+
+Types:
+
+```python
+from runloop_api_client.types.devboxes import BrowserView
+```
+
+Methods:
+
+- client.devboxes.browsers.create() -> BrowserView
+
+## Computers
+
+Types:
+
+```python
+from runloop_api_client.types.devboxes import (
+ ComputerView,
+ ComputerKeyboardInteractionResponse,
+ ComputerMouseInteractionResponse,
+ ComputerScreenInteractionResponse,
+)
+```
+
+Methods:
+
+- client.devboxes.computers.create(\*\*params) -> ComputerView
+- client.devboxes.computers.keyboard_interaction(id, \*\*params) -> ComputerKeyboardInteractionResponse
+- client.devboxes.computers.mouse_interaction(id, \*\*params) -> ComputerMouseInteractionResponse
+- client.devboxes.computers.screen_interaction(id, \*\*params) -> ComputerScreenInteractionResponse
+
## Lsp
Types:
diff --git a/pyproject.toml b/pyproject.toml
index 87f3f45c..f02034ee 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "runloop_api_client"
-version = "0.15.0"
+version = "0.16.0"
description = "The official Python library for the runloop API"
dynamic = ["readme"]
license = "MIT"
@@ -129,6 +129,7 @@ testpaths = ["tests"]
addopts = "--tb=short"
xfail_strict = true
asyncio_mode = "auto"
+asyncio_default_fixture_loop_scope = "session"
filterwarnings = [
"error"
]
diff --git a/scripts/bootstrap b/scripts/bootstrap
index 8c5c60eb..e84fe62c 100755
--- a/scripts/bootstrap
+++ b/scripts/bootstrap
@@ -4,7 +4,7 @@ set -e
cd "$(dirname "$0")/.."
-if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then
+if ! command -v rye >/dev/null 2>&1 && [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then
brew bundle check >/dev/null 2>&1 || {
echo "==> Installing Homebrew dependencies…"
brew bundle
diff --git a/scripts/lint b/scripts/lint
index e4375378..6736f5cf 100755
--- a/scripts/lint
+++ b/scripts/lint
@@ -9,4 +9,3 @@ rye run lint
echo "==> Making sure it imports"
rye run python -c 'import runloop_api_client'
-
diff --git a/src/runloop_api_client/_response.py b/src/runloop_api_client/_response.py
index d765ed40..1e0ab213 100644
--- a/src/runloop_api_client/_response.py
+++ b/src/runloop_api_client/_response.py
@@ -136,6 +136,8 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
if cast_to and is_annotated_type(cast_to):
cast_to = extract_type_arg(cast_to, 0)
+ origin = get_origin(cast_to) or cast_to
+
if self._is_sse_stream:
if to:
if not is_stream_class_type(to):
@@ -195,8 +197,6 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
if cast_to == bool:
return cast(R, response.text.lower() == "true")
- origin = get_origin(cast_to) or cast_to
-
if origin == APIResponse:
raise RuntimeError("Unexpected state - cast_to is `APIResponse`")
diff --git a/src/runloop_api_client/_version.py b/src/runloop_api_client/_version.py
index c75e8e65..e302279f 100644
--- a/src/runloop_api_client/_version.py
+++ b/src/runloop_api_client/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "runloop_api_client"
-__version__ = "0.15.0" # x-release-please-version
+__version__ = "0.16.0" # x-release-please-version
diff --git a/src/runloop_api_client/resources/benchmarks/benchmarks.py b/src/runloop_api_client/resources/benchmarks/benchmarks.py
index 9b016c68..65049475 100644
--- a/src/runloop_api_client/resources/benchmarks/benchmarks.py
+++ b/src/runloop_api_client/resources/benchmarks/benchmarks.py
@@ -147,6 +147,7 @@ def list(
self,
*,
limit: int | NotGiven = NOT_GIVEN,
+ public: bool | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -161,6 +162,9 @@ def list(
Args:
limit: The limit of items to return. Default is 20.
+ public: List public benchmarks, e.g. SWE-bench. Defaults to false, i.e. only
+ user-defined benchmarks are listed.
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -181,6 +185,7 @@ def list(
query=maybe_transform(
{
"limit": limit,
+ "public": public,
"starting_after": starting_after,
},
benchmark_list_params.BenchmarkListParams,
@@ -351,6 +356,7 @@ async def list(
self,
*,
limit: int | NotGiven = NOT_GIVEN,
+ public: bool | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -365,6 +371,9 @@ async def list(
Args:
limit: The limit of items to return. Default is 20.
+ public: List public benchmarks, e.g. SWE-bench. Defaults to false, i.e. only
+ user-defined benchmarks are listed.
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -385,6 +394,7 @@ async def list(
query=await async_maybe_transform(
{
"limit": limit,
+ "public": public,
"starting_after": starting_after,
},
benchmark_list_params.BenchmarkListParams,
diff --git a/src/runloop_api_client/resources/benchmarks/runs.py b/src/runloop_api_client/resources/benchmarks/runs.py
index 3a552734..3866eb99 100644
--- a/src/runloop_api_client/resources/benchmarks/runs.py
+++ b/src/runloop_api_client/resources/benchmarks/runs.py
@@ -81,6 +81,7 @@ def retrieve(
def list(
self,
*,
+ benchmark_id: str | NotGiven = NOT_GIVEN,
limit: int | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -94,6 +95,8 @@ def list(
List all BenchmarkRuns matching filter.
Args:
+ benchmark_id: The Benchmark ID to filter by.
+
limit: The limit of items to return. Default is 20.
starting_after: Load the next page of data starting after the item with the given ID.
@@ -115,6 +118,7 @@ def list(
timeout=timeout,
query=maybe_transform(
{
+ "benchmark_id": benchmark_id,
"limit": limit,
"starting_after": starting_after,
},
@@ -221,6 +225,7 @@ async def retrieve(
async def list(
self,
*,
+ benchmark_id: str | NotGiven = NOT_GIVEN,
limit: int | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -234,6 +239,8 @@ async def list(
List all BenchmarkRuns matching filter.
Args:
+ benchmark_id: The Benchmark ID to filter by.
+
limit: The limit of items to return. Default is 20.
starting_after: Load the next page of data starting after the item with the given ID.
@@ -255,6 +262,7 @@ async def list(
timeout=timeout,
query=await async_maybe_transform(
{
+ "benchmark_id": benchmark_id,
"limit": limit,
"starting_after": starting_after,
},
diff --git a/src/runloop_api_client/resources/devboxes/__init__.py b/src/runloop_api_client/resources/devboxes/__init__.py
index d5378fb5..1e09245d 100644
--- a/src/runloop_api_client/resources/devboxes/__init__.py
+++ b/src/runloop_api_client/resources/devboxes/__init__.py
@@ -16,6 +16,14 @@
LogsResourceWithStreamingResponse,
AsyncLogsResourceWithStreamingResponse,
)
+from .browsers import (
+ BrowsersResource,
+ AsyncBrowsersResource,
+ BrowsersResourceWithRawResponse,
+ AsyncBrowsersResourceWithRawResponse,
+ BrowsersResourceWithStreamingResponse,
+ AsyncBrowsersResourceWithStreamingResponse,
+)
from .devboxes import (
DevboxesResource,
AsyncDevboxesResource,
@@ -24,6 +32,14 @@
DevboxesResourceWithStreamingResponse,
AsyncDevboxesResourceWithStreamingResponse,
)
+from .computers import (
+ ComputersResource,
+ AsyncComputersResource,
+ ComputersResourceWithRawResponse,
+ AsyncComputersResourceWithRawResponse,
+ ComputersResourceWithStreamingResponse,
+ AsyncComputersResourceWithStreamingResponse,
+)
from .executions import (
ExecutionsResource,
AsyncExecutionsResource,
@@ -34,6 +50,18 @@
)
__all__ = [
+ "BrowsersResource",
+ "AsyncBrowsersResource",
+ "BrowsersResourceWithRawResponse",
+ "AsyncBrowsersResourceWithRawResponse",
+ "BrowsersResourceWithStreamingResponse",
+ "AsyncBrowsersResourceWithStreamingResponse",
+ "ComputersResource",
+ "AsyncComputersResource",
+ "ComputersResourceWithRawResponse",
+ "AsyncComputersResourceWithRawResponse",
+ "ComputersResourceWithStreamingResponse",
+ "AsyncComputersResourceWithStreamingResponse",
"LspResource",
"AsyncLspResource",
"LspResourceWithRawResponse",
diff --git a/src/runloop_api_client/resources/devboxes/browsers.py b/src/runloop_api_client/resources/devboxes/browsers.py
new file mode 100644
index 00000000..59d264bc
--- /dev/null
+++ b/src/runloop_api_client/resources/devboxes/browsers.py
@@ -0,0 +1,155 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..._base_client import make_request_options
+from ...types.devboxes.browser_view import BrowserView
+
+__all__ = ["BrowsersResource", "AsyncBrowsersResource"]
+
+
+class BrowsersResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> BrowsersResourceWithRawResponse:
+ """
+ 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/runloopai/api-client-python#accessing-raw-response-data-eg-headers
+ """
+ return BrowsersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> BrowsersResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response
+ """
+ return BrowsersResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ # 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,
+ idempotency_key: str | None = None,
+ ) -> BrowserView:
+ """Create a Devbox that has a managed Browser and begin the boot process.
+
+ As part
+ of booting the Devbox, the browser will automatically be started with connection
+ utilities activated.
+ """
+ return self._post(
+ "/v1/devboxes/browsers",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=BrowserView,
+ )
+
+
+class AsyncBrowsersResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncBrowsersResourceWithRawResponse:
+ """
+ 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/runloopai/api-client-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncBrowsersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncBrowsersResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response
+ """
+ return AsyncBrowsersResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ # 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,
+ idempotency_key: str | None = None,
+ ) -> BrowserView:
+ """Create a Devbox that has a managed Browser and begin the boot process.
+
+ As part
+ of booting the Devbox, the browser will automatically be started with connection
+ utilities activated.
+ """
+ return await self._post(
+ "/v1/devboxes/browsers",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=BrowserView,
+ )
+
+
+class BrowsersResourceWithRawResponse:
+ def __init__(self, browsers: BrowsersResource) -> None:
+ self._browsers = browsers
+
+ self.create = to_raw_response_wrapper(
+ browsers.create,
+ )
+
+
+class AsyncBrowsersResourceWithRawResponse:
+ def __init__(self, browsers: AsyncBrowsersResource) -> None:
+ self._browsers = browsers
+
+ self.create = async_to_raw_response_wrapper(
+ browsers.create,
+ )
+
+
+class BrowsersResourceWithStreamingResponse:
+ def __init__(self, browsers: BrowsersResource) -> None:
+ self._browsers = browsers
+
+ self.create = to_streamed_response_wrapper(
+ browsers.create,
+ )
+
+
+class AsyncBrowsersResourceWithStreamingResponse:
+ def __init__(self, browsers: AsyncBrowsersResource) -> None:
+ self._browsers = browsers
+
+ self.create = async_to_streamed_response_wrapper(
+ browsers.create,
+ )
diff --git a/src/runloop_api_client/resources/devboxes/computers.py b/src/runloop_api_client/resources/devboxes/computers.py
new file mode 100644
index 00000000..c1079130
--- /dev/null
+++ b/src/runloop_api_client/resources/devboxes/computers.py
@@ -0,0 +1,559 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal
+
+import httpx
+
+from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from ..._utils import (
+ maybe_transform,
+ async_maybe_transform,
+)
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..._base_client import make_request_options
+from ...types.devboxes import (
+ computer_create_params,
+ computer_mouse_interaction_params,
+ computer_screen_interaction_params,
+ computer_keyboard_interaction_params,
+)
+from ...types.devboxes.computer_view import ComputerView
+from ...types.devboxes.computer_mouse_interaction_response import ComputerMouseInteractionResponse
+from ...types.devboxes.computer_screen_interaction_response import ComputerScreenInteractionResponse
+from ...types.devboxes.computer_keyboard_interaction_response import ComputerKeyboardInteractionResponse
+
+__all__ = ["ComputersResource", "AsyncComputersResource"]
+
+
+class ComputersResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ComputersResourceWithRawResponse:
+ """
+ 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/runloopai/api-client-python#accessing-raw-response-data-eg-headers
+ """
+ return ComputersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ComputersResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response
+ """
+ return ComputersResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ display_dimensions: Optional[computer_create_params.DisplayDimensions] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> ComputerView:
+ """Create a Computer and begin the boot process.
+
+ The Computer will initially launch
+ in the 'provisioning' state while Runloop allocates the necessary
+ infrastructure. It will transition to the 'initializing' state while the booted
+ Computer runs any Runloop or user defined set up scripts. Finally, the Computer
+ will transition to the 'running' state when it is ready for use.
+
+ Args:
+ display_dimensions: Customize the dimensions of the computer display.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ return self._post(
+ "/v1/devboxes/computers",
+ body=maybe_transform(
+ {"display_dimensions": display_dimensions}, computer_create_params.ComputerCreateParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerView,
+ )
+
+ def keyboard_interaction(
+ self,
+ id: str,
+ *,
+ action: Literal["key", "type"],
+ text: Optional[str] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> ComputerKeyboardInteractionResponse:
+ """
+ Perform the specified keyboard interaction on the Computer identified by the
+ given ID.
+
+ Args:
+ action: The keyboard action to perform.
+
+ text: The text to type or the key (with optional modifier) to press.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ f"/v1/devboxes/computers/{id}/keyboard_interaction",
+ body=maybe_transform(
+ {
+ "action": action,
+ "text": text,
+ },
+ computer_keyboard_interaction_params.ComputerKeyboardInteractionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerKeyboardInteractionResponse,
+ )
+
+ def mouse_interaction(
+ self,
+ id: str,
+ *,
+ action: Literal["mouse_move", "left_click", "left_click_drag", "right_click", "middle_click", "double_click"],
+ coordinate: Optional[computer_mouse_interaction_params.Coordinate] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> ComputerMouseInteractionResponse:
+ """
+ Perform the specified mouse interaction on the Computer identified by the given
+ ID.
+
+ Args:
+ action: The mouse action to perform.
+
+ coordinate: The x (pixels from the left) and y (pixels from the top) coordinates for the
+ mouse to move or click-drag. Required only by `action=mouse_move` or
+ `action=left_click_drag`
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ f"/v1/devboxes/computers/{id}/mouse_interaction",
+ body=maybe_transform(
+ {
+ "action": action,
+ "coordinate": coordinate,
+ },
+ computer_mouse_interaction_params.ComputerMouseInteractionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerMouseInteractionResponse,
+ )
+
+ def screen_interaction(
+ self,
+ id: str,
+ *,
+ action: Literal["screenshot", "cursor_position"],
+ # 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,
+ idempotency_key: str | None = None,
+ ) -> ComputerScreenInteractionResponse:
+ """
+ Perform the specified screen interaction on the Computer identified by the given
+ ID.
+
+ Args:
+ action: The screen action to perform.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ f"/v1/devboxes/computers/{id}/screen_interaction",
+ body=maybe_transform(
+ {"action": action}, computer_screen_interaction_params.ComputerScreenInteractionParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerScreenInteractionResponse,
+ )
+
+
+class AsyncComputersResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncComputersResourceWithRawResponse:
+ """
+ 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/runloopai/api-client-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncComputersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncComputersResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response
+ """
+ return AsyncComputersResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ display_dimensions: Optional[computer_create_params.DisplayDimensions] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> ComputerView:
+ """Create a Computer and begin the boot process.
+
+ The Computer will initially launch
+ in the 'provisioning' state while Runloop allocates the necessary
+ infrastructure. It will transition to the 'initializing' state while the booted
+ Computer runs any Runloop or user defined set up scripts. Finally, the Computer
+ will transition to the 'running' state when it is ready for use.
+
+ Args:
+ display_dimensions: Customize the dimensions of the computer display.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ return await self._post(
+ "/v1/devboxes/computers",
+ body=await async_maybe_transform(
+ {"display_dimensions": display_dimensions}, computer_create_params.ComputerCreateParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerView,
+ )
+
+ async def keyboard_interaction(
+ self,
+ id: str,
+ *,
+ action: Literal["key", "type"],
+ text: Optional[str] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> ComputerKeyboardInteractionResponse:
+ """
+ Perform the specified keyboard interaction on the Computer identified by the
+ given ID.
+
+ Args:
+ action: The keyboard action to perform.
+
+ text: The text to type or the key (with optional modifier) to press.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ f"/v1/devboxes/computers/{id}/keyboard_interaction",
+ body=await async_maybe_transform(
+ {
+ "action": action,
+ "text": text,
+ },
+ computer_keyboard_interaction_params.ComputerKeyboardInteractionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerKeyboardInteractionResponse,
+ )
+
+ async def mouse_interaction(
+ self,
+ id: str,
+ *,
+ action: Literal["mouse_move", "left_click", "left_click_drag", "right_click", "middle_click", "double_click"],
+ coordinate: Optional[computer_mouse_interaction_params.Coordinate] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> ComputerMouseInteractionResponse:
+ """
+ Perform the specified mouse interaction on the Computer identified by the given
+ ID.
+
+ Args:
+ action: The mouse action to perform.
+
+ coordinate: The x (pixels from the left) and y (pixels from the top) coordinates for the
+ mouse to move or click-drag. Required only by `action=mouse_move` or
+ `action=left_click_drag`
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ f"/v1/devboxes/computers/{id}/mouse_interaction",
+ body=await async_maybe_transform(
+ {
+ "action": action,
+ "coordinate": coordinate,
+ },
+ computer_mouse_interaction_params.ComputerMouseInteractionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerMouseInteractionResponse,
+ )
+
+ async def screen_interaction(
+ self,
+ id: str,
+ *,
+ action: Literal["screenshot", "cursor_position"],
+ # 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,
+ idempotency_key: str | None = None,
+ ) -> ComputerScreenInteractionResponse:
+ """
+ Perform the specified screen interaction on the Computer identified by the given
+ ID.
+
+ Args:
+ action: The screen action to perform.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ f"/v1/devboxes/computers/{id}/screen_interaction",
+ body=await async_maybe_transform(
+ {"action": action}, computer_screen_interaction_params.ComputerScreenInteractionParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=ComputerScreenInteractionResponse,
+ )
+
+
+class ComputersResourceWithRawResponse:
+ def __init__(self, computers: ComputersResource) -> None:
+ self._computers = computers
+
+ self.create = to_raw_response_wrapper(
+ computers.create,
+ )
+ self.keyboard_interaction = to_raw_response_wrapper(
+ computers.keyboard_interaction,
+ )
+ self.mouse_interaction = to_raw_response_wrapper(
+ computers.mouse_interaction,
+ )
+ self.screen_interaction = to_raw_response_wrapper(
+ computers.screen_interaction,
+ )
+
+
+class AsyncComputersResourceWithRawResponse:
+ def __init__(self, computers: AsyncComputersResource) -> None:
+ self._computers = computers
+
+ self.create = async_to_raw_response_wrapper(
+ computers.create,
+ )
+ self.keyboard_interaction = async_to_raw_response_wrapper(
+ computers.keyboard_interaction,
+ )
+ self.mouse_interaction = async_to_raw_response_wrapper(
+ computers.mouse_interaction,
+ )
+ self.screen_interaction = async_to_raw_response_wrapper(
+ computers.screen_interaction,
+ )
+
+
+class ComputersResourceWithStreamingResponse:
+ def __init__(self, computers: ComputersResource) -> None:
+ self._computers = computers
+
+ self.create = to_streamed_response_wrapper(
+ computers.create,
+ )
+ self.keyboard_interaction = to_streamed_response_wrapper(
+ computers.keyboard_interaction,
+ )
+ self.mouse_interaction = to_streamed_response_wrapper(
+ computers.mouse_interaction,
+ )
+ self.screen_interaction = to_streamed_response_wrapper(
+ computers.screen_interaction,
+ )
+
+
+class AsyncComputersResourceWithStreamingResponse:
+ def __init__(self, computers: AsyncComputersResource) -> None:
+ self._computers = computers
+
+ self.create = async_to_streamed_response_wrapper(
+ computers.create,
+ )
+ self.keyboard_interaction = async_to_streamed_response_wrapper(
+ computers.keyboard_interaction,
+ )
+ self.mouse_interaction = async_to_streamed_response_wrapper(
+ computers.mouse_interaction,
+ )
+ self.screen_interaction = async_to_streamed_response_wrapper(
+ computers.screen_interaction,
+ )
diff --git a/src/runloop_api_client/resources/devboxes/devboxes.py b/src/runloop_api_client/resources/devboxes/devboxes.py
index 3d27b145..14bd900a 100644
--- a/src/runloop_api_client/resources/devboxes/devboxes.py
+++ b/src/runloop_api_client/resources/devboxes/devboxes.py
@@ -44,7 +44,23 @@
deepcopy_minimal,
async_maybe_transform,
)
+from .browsers import (
+ BrowsersResource,
+ AsyncBrowsersResource,
+ BrowsersResourceWithRawResponse,
+ AsyncBrowsersResourceWithRawResponse,
+ BrowsersResourceWithStreamingResponse,
+ AsyncBrowsersResourceWithStreamingResponse,
+)
from ..._compat import cached_property
+from .computers import (
+ ComputersResource,
+ AsyncComputersResource,
+ ComputersResourceWithRawResponse,
+ AsyncComputersResourceWithRawResponse,
+ ComputersResourceWithStreamingResponse,
+ AsyncComputersResourceWithStreamingResponse,
+)
from .executions import (
ExecutionsResource,
AsyncExecutionsResource,
@@ -92,6 +108,14 @@
DEVBOX_BOOTING_STATES = frozenset(('provisioning', 'initializing'))
class DevboxesResource(SyncAPIResource):
+ @cached_property
+ def browsers(self) -> BrowsersResource:
+ return BrowsersResource(self._client)
+
+ @cached_property
+ def computers(self) -> ComputersResource:
+ return ComputersResource(self._client)
+
@cached_property
def lsp(self) -> LspResource:
return LspResource(self._client)
@@ -1215,6 +1239,14 @@ def write_file_contents(
class AsyncDevboxesResource(AsyncAPIResource):
+ @cached_property
+ def browsers(self) -> AsyncBrowsersResource:
+ return AsyncBrowsersResource(self._client)
+
+ @cached_property
+ def computers(self) -> AsyncComputersResource:
+ return AsyncComputersResource(self._client)
+
@cached_property
def lsp(self) -> AsyncLspResource:
return AsyncLspResource(self._client)
@@ -2397,6 +2429,14 @@ def __init__(self, devboxes: DevboxesResource) -> None:
devboxes.write_file_contents,
)
+ @cached_property
+ def browsers(self) -> BrowsersResourceWithRawResponse:
+ return BrowsersResourceWithRawResponse(self._devboxes.browsers)
+
+ @cached_property
+ def computers(self) -> ComputersResourceWithRawResponse:
+ return ComputersResourceWithRawResponse(self._devboxes.computers)
+
@cached_property
def lsp(self) -> LspResourceWithRawResponse:
return LspResourceWithRawResponse(self._devboxes.lsp)
@@ -2473,6 +2513,14 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None:
devboxes.write_file_contents,
)
+ @cached_property
+ def browsers(self) -> AsyncBrowsersResourceWithRawResponse:
+ return AsyncBrowsersResourceWithRawResponse(self._devboxes.browsers)
+
+ @cached_property
+ def computers(self) -> AsyncComputersResourceWithRawResponse:
+ return AsyncComputersResourceWithRawResponse(self._devboxes.computers)
+
@cached_property
def lsp(self) -> AsyncLspResourceWithRawResponse:
return AsyncLspResourceWithRawResponse(self._devboxes.lsp)
@@ -2549,6 +2597,14 @@ def __init__(self, devboxes: DevboxesResource) -> None:
devboxes.write_file_contents,
)
+ @cached_property
+ def browsers(self) -> BrowsersResourceWithStreamingResponse:
+ return BrowsersResourceWithStreamingResponse(self._devboxes.browsers)
+
+ @cached_property
+ def computers(self) -> ComputersResourceWithStreamingResponse:
+ return ComputersResourceWithStreamingResponse(self._devboxes.computers)
+
@cached_property
def lsp(self) -> LspResourceWithStreamingResponse:
return LspResourceWithStreamingResponse(self._devboxes.lsp)
@@ -2625,6 +2681,14 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None:
devboxes.write_file_contents,
)
+ @cached_property
+ def browsers(self) -> AsyncBrowsersResourceWithStreamingResponse:
+ return AsyncBrowsersResourceWithStreamingResponse(self._devboxes.browsers)
+
+ @cached_property
+ def computers(self) -> AsyncComputersResourceWithStreamingResponse:
+ return AsyncComputersResourceWithStreamingResponse(self._devboxes.computers)
+
@cached_property
def lsp(self) -> AsyncLspResourceWithStreamingResponse:
return AsyncLspResourceWithStreamingResponse(self._devboxes.lsp)
diff --git a/src/runloop_api_client/resources/scenarios/runs.py b/src/runloop_api_client/resources/scenarios/runs.py
index cec29302..2226123a 100644
--- a/src/runloop_api_client/resources/scenarios/runs.py
+++ b/src/runloop_api_client/resources/scenarios/runs.py
@@ -82,6 +82,7 @@ def list(
self,
*,
limit: int | NotGiven = NOT_GIVEN,
+ scenario_id: bool | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -96,6 +97,8 @@ def list(
Args:
limit: The limit of items to return. Default is 20.
+ scenario_id: Filter runs associated to Scenario given ID
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -116,6 +119,7 @@ def list(
query=maybe_transform(
{
"limit": limit,
+ "scenario_id": scenario_id,
"starting_after": starting_after,
},
run_list_params.RunListParams,
@@ -262,6 +266,7 @@ async def list(
self,
*,
limit: int | NotGiven = NOT_GIVEN,
+ scenario_id: bool | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -276,6 +281,8 @@ async def list(
Args:
limit: The limit of items to return. Default is 20.
+ scenario_id: Filter runs associated to Scenario given ID
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -296,6 +303,7 @@ async def list(
query=await async_maybe_transform(
{
"limit": limit,
+ "scenario_id": scenario_id,
"starting_after": starting_after,
},
run_list_params.RunListParams,
diff --git a/src/runloop_api_client/types/benchmark_list_params.py b/src/runloop_api_client/types/benchmark_list_params.py
index 51b2b132..3eef4e03 100644
--- a/src/runloop_api_client/types/benchmark_list_params.py
+++ b/src/runloop_api_client/types/benchmark_list_params.py
@@ -11,5 +11,11 @@ class BenchmarkListParams(TypedDict, total=False):
limit: int
"""The limit of items to return. Default is 20."""
+ public: bool
+ """List public benchmarks, e.g.
+
+ SWE-bench. Defaults to false, i.e. only user-defined benchmarks are listed.
+ """
+
starting_after: str
"""Load the next page of data starting after the item with the given ID."""
diff --git a/src/runloop_api_client/types/benchmark_run_view.py b/src/runloop_api_client/types/benchmark_run_view.py
index 08507340..bce32b0c 100644
--- a/src/runloop_api_client/types/benchmark_run_view.py
+++ b/src/runloop_api_client/types/benchmark_run_view.py
@@ -20,3 +20,9 @@ class BenchmarkRunView(BaseModel):
name: Optional[str] = None
"""The name of the BenchmarkRun."""
+
+ score: Optional[float] = None
+ """The final score across the BenchmarkRun, present once completed.
+
+ Calculated as sum of scenario scores / number of scenario runs.
+ """
diff --git a/src/runloop_api_client/types/benchmarks/run_list_params.py b/src/runloop_api_client/types/benchmarks/run_list_params.py
index a8be85a7..f93695b2 100644
--- a/src/runloop_api_client/types/benchmarks/run_list_params.py
+++ b/src/runloop_api_client/types/benchmarks/run_list_params.py
@@ -8,6 +8,9 @@
class RunListParams(TypedDict, total=False):
+ benchmark_id: str
+ """The Benchmark ID to filter by."""
+
limit: int
"""The limit of items to return. Default is 20."""
diff --git a/src/runloop_api_client/types/devbox_view.py b/src/runloop_api_client/types/devbox_view.py
index 838a5ea7..f645afde 100644
--- a/src/runloop_api_client/types/devbox_view.py
+++ b/src/runloop_api_client/types/devbox_view.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, Optional
+from typing import Dict, List, Optional
from typing_extensions import Literal
from .._models import BaseModel
@@ -13,6 +13,13 @@ class DevboxView(BaseModel):
id: str
"""The ID of the Devbox."""
+ capabilities: List[Literal["unknown", "computer_usage", "browser_usage"]]
+ """A list of capability groups this devbox has access to.
+
+ This allows devboxes to be compatible with certain tools sets like computer
+ usage APIs.
+ """
+
create_time_ms: int
"""Creation time of the Devbox (Unix timestamp milliseconds)."""
diff --git a/src/runloop_api_client/types/devboxes/__init__.py b/src/runloop_api_client/types/devboxes/__init__.py
index 30d13b0f..92ea981d 100644
--- a/src/runloop_api_client/types/devboxes/__init__.py
+++ b/src/runloop_api_client/types/devboxes/__init__.py
@@ -16,8 +16,10 @@
from .symbol_kind import SymbolKind as SymbolKind
from .symbol_type import SymbolType as SymbolType
from .base_command import BaseCommand as BaseCommand
+from .browser_view import BrowserView as BrowserView
from .document_uri import DocumentUri as DocumentUri
from .base_location import BaseLocation as BaseLocation
+from .computer_view import ComputerView as ComputerView
from .base_signature import BaseSignature as BaseSignature
from .diagnostic_tag import DiagnosticTag as DiagnosticTag
from .l_sp_any_param import LSpAnyParam as LSpAnyParam
@@ -44,6 +46,7 @@
from .lsp_references_params import LspReferencesParams as LspReferencesParams
from .watched_file_response import WatchedFileResponse as WatchedFileResponse
from .code_description_param import CodeDescriptionParam as CodeDescriptionParam
+from .computer_create_params import ComputerCreateParams as ComputerCreateParams
from .file_contents_response import FileContentsResponse as FileContentsResponse
from .health_status_response import HealthStatusResponse as HealthStatusResponse
from .lsp_diagnostics_params import LspDiagnosticsParams as LspDiagnosticsParams
@@ -66,8 +69,16 @@
from .lsp_set_watch_directory_params import LspSetWatchDirectoryParams as LspSetWatchDirectoryParams
from .lsp_get_code_segment_info_params import LspGetCodeSegmentInfoParams as LspGetCodeSegmentInfoParams
from .lsp_set_watch_directory_response import LspSetWatchDirectoryResponse as LspSetWatchDirectoryResponse
+from .computer_mouse_interaction_params import ComputerMouseInteractionParams as ComputerMouseInteractionParams
+from .computer_screen_interaction_params import ComputerScreenInteractionParams as ComputerScreenInteractionParams
+from .computer_mouse_interaction_response import ComputerMouseInteractionResponse as ComputerMouseInteractionResponse
from .record_string_text_edit_array_param import RecordStringTextEditArrayParam as RecordStringTextEditArrayParam
+from .computer_keyboard_interaction_params import ComputerKeyboardInteractionParams as ComputerKeyboardInteractionParams
+from .computer_screen_interaction_response import ComputerScreenInteractionResponse as ComputerScreenInteractionResponse
from .diagnostic_related_information_param import DiagnosticRelatedInformationParam as DiagnosticRelatedInformationParam
+from .computer_keyboard_interaction_response import (
+ ComputerKeyboardInteractionResponse as ComputerKeyboardInteractionResponse,
+)
from .lsp_get_code_actions_for_diagnostic_params import (
LspGetCodeActionsForDiagnosticParams as LspGetCodeActionsForDiagnosticParams,
)
diff --git a/src/runloop_api_client/types/devboxes/browser_view.py b/src/runloop_api_client/types/devboxes/browser_view.py
new file mode 100644
index 00000000..ef9303f0
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/browser_view.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+
+from ..._models import BaseModel
+from ..devbox_view import DevboxView
+
+__all__ = ["BrowserView"]
+
+
+class BrowserView(BaseModel):
+ connection_url: str
+ """
+ The url to enable remote connection from browser automation tools like
+ playwright.
+ """
+
+ devbox: DevboxView
+ """The underlying devbox the browser setup is running on."""
+
+ live_view_url: str
+ """
+ The url to view the browser window and enable user interactions via their own
+ browser.
+ """
diff --git a/src/runloop_api_client/types/devboxes/computer_create_params.py b/src/runloop_api_client/types/devboxes/computer_create_params.py
new file mode 100644
index 00000000..15c00cff
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_create_params.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ComputerCreateParams", "DisplayDimensions"]
+
+
+class ComputerCreateParams(TypedDict, total=False):
+ display_dimensions: Optional[DisplayDimensions]
+ """Customize the dimensions of the computer display."""
+
+
+class DisplayDimensions(TypedDict, total=False):
+ display_height_px: Required[int]
+ """The height of the display being controlled by the model in pixels."""
+
+ display_width_px: Required[int]
+ """The width of the display being controlled by the model in pixels."""
diff --git a/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_params.py b/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_params.py
new file mode 100644
index 00000000..c7c2a8f3
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_params.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ComputerKeyboardInteractionParams"]
+
+
+class ComputerKeyboardInteractionParams(TypedDict, total=False):
+ action: Required[Literal["key", "type"]]
+ """The keyboard action to perform."""
+
+ text: Optional[str]
+ """The text to type or the key (with optional modifier) to press."""
diff --git a/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_response.py b/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_response.py
new file mode 100644
index 00000000..6990bc74
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ComputerKeyboardInteractionResponse"]
+
+
+class ComputerKeyboardInteractionResponse(BaseModel):
+ error: Optional[str] = None
+
+ latest_screenshot_base64_img: Optional[str] = None
+
+ output: Optional[str] = None
diff --git a/src/runloop_api_client/types/devboxes/computer_mouse_interaction_params.py b/src/runloop_api_client/types/devboxes/computer_mouse_interaction_params.py
new file mode 100644
index 00000000..b28a0723
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_mouse_interaction_params.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ComputerMouseInteractionParams", "Coordinate"]
+
+
+class ComputerMouseInteractionParams(TypedDict, total=False):
+ action: Required[
+ Literal["mouse_move", "left_click", "left_click_drag", "right_click", "middle_click", "double_click"]
+ ]
+ """The mouse action to perform."""
+
+ coordinate: Optional[Coordinate]
+ """
+ The x (pixels from the left) and y (pixels from the top) coordinates for the
+ mouse to move or click-drag. Required only by `action=mouse_move` or
+ `action=left_click_drag`
+ """
+
+
+class Coordinate(TypedDict, total=False):
+ x: Required[int]
+ """The x coordinate (pixels from the left) for the mouse to move or click-drag."""
+
+ y: Required[int]
+ """The y coordinate (pixels from the top) for the mouse to move or click-drag."""
diff --git a/src/runloop_api_client/types/devboxes/computer_mouse_interaction_response.py b/src/runloop_api_client/types/devboxes/computer_mouse_interaction_response.py
new file mode 100644
index 00000000..cbaab9dc
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_mouse_interaction_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ComputerMouseInteractionResponse"]
+
+
+class ComputerMouseInteractionResponse(BaseModel):
+ error: Optional[str] = None
+
+ latest_screenshot_base64_img: Optional[str] = None
+
+ output: Optional[str] = None
diff --git a/src/runloop_api_client/types/devboxes/computer_screen_interaction_params.py b/src/runloop_api_client/types/devboxes/computer_screen_interaction_params.py
new file mode 100644
index 00000000..8423249b
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_screen_interaction_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ComputerScreenInteractionParams"]
+
+
+class ComputerScreenInteractionParams(TypedDict, total=False):
+ action: Required[Literal["screenshot", "cursor_position"]]
+ """The screen action to perform."""
diff --git a/src/runloop_api_client/types/devboxes/computer_screen_interaction_response.py b/src/runloop_api_client/types/devboxes/computer_screen_interaction_response.py
new file mode 100644
index 00000000..3ad4cb5c
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_screen_interaction_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ComputerScreenInteractionResponse"]
+
+
+class ComputerScreenInteractionResponse(BaseModel):
+ error: Optional[str] = None
+
+ latest_screenshot_base64_img: Optional[str] = None
+
+ output: Optional[str] = None
diff --git a/src/runloop_api_client/types/devboxes/computer_view.py b/src/runloop_api_client/types/devboxes/computer_view.py
new file mode 100644
index 00000000..858aa27a
--- /dev/null
+++ b/src/runloop_api_client/types/devboxes/computer_view.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+
+from ..._models import BaseModel
+from ..devbox_view import DevboxView
+
+__all__ = ["ComputerView"]
+
+
+class ComputerView(BaseModel):
+ devbox: DevboxView
+ """The underlying devbox the computer setup is running on."""
+
+ live_screen_url: str
+ """The http tunnel to connect and view the live screen of the computer."""
diff --git a/src/runloop_api_client/types/scenario_run_view.py b/src/runloop_api_client/types/scenario_run_view.py
index 33c18100..33da1722 100644
--- a/src/runloop_api_client/types/scenario_run_view.py
+++ b/src/runloop_api_client/types/scenario_run_view.py
@@ -19,7 +19,7 @@ class ScenarioRunView(BaseModel):
scenario_id: str
"""ID of the Scenario that has been run."""
- state: Literal["running", "scoring", "completed", "canceled", "timeout", "failed"]
+ state: Literal["running", "scoring", "scored", "completed", "canceled", "timeout", "failed"]
"""The state of the ScenarioRun."""
benchmark_run_id: Optional[str] = None
@@ -28,5 +28,8 @@ class ScenarioRunView(BaseModel):
duration_ms: Optional[int] = None
"""Duration scenario took to run."""
+ name: Optional[str] = None
+ """Optional name of ScenarioRun."""
+
scoring_contract_result: Optional[ScoringContractResultView] = None
"""The input context for the Scenario."""
diff --git a/src/runloop_api_client/types/scenarios/run_list_params.py b/src/runloop_api_client/types/scenarios/run_list_params.py
index a8be85a7..86a3b1ef 100644
--- a/src/runloop_api_client/types/scenarios/run_list_params.py
+++ b/src/runloop_api_client/types/scenarios/run_list_params.py
@@ -11,5 +11,8 @@ class RunListParams(TypedDict, total=False):
limit: int
"""The limit of items to return. Default is 20."""
+ scenario_id: bool
+ """Filter runs associated to Scenario given ID"""
+
starting_after: str
"""Load the next page of data starting after the item with the given ID."""
diff --git a/tests/api_resources/benchmarks/test_runs.py b/tests/api_resources/benchmarks/test_runs.py
index 6f7ac0b8..31ca76fe 100644
--- a/tests/api_resources/benchmarks/test_runs.py
+++ b/tests/api_resources/benchmarks/test_runs.py
@@ -63,6 +63,7 @@ def test_method_list(self, client: Runloop) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Runloop) -> None:
run = client.benchmarks.runs.list(
+ benchmark_id="benchmark_id",
limit=0,
starting_after="starting_after",
)
@@ -176,6 +177,7 @@ async def test_method_list(self, async_client: AsyncRunloop) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> None:
run = await async_client.benchmarks.runs.list(
+ benchmark_id="benchmark_id",
limit=0,
starting_after="starting_after",
)
diff --git a/tests/api_resources/devboxes/test_browsers.py b/tests/api_resources/devboxes/test_browsers.py
new file mode 100644
index 00000000..9b1a51a2
--- /dev/null
+++ b/tests/api_resources/devboxes/test_browsers.py
@@ -0,0 +1,72 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from tests.utils import assert_matches_type
+from runloop_api_client import Runloop, AsyncRunloop
+from runloop_api_client.types.devboxes import BrowserView
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestBrowsers:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Runloop) -> None:
+ browser = client.devboxes.browsers.create()
+ assert_matches_type(BrowserView, browser, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Runloop) -> None:
+ response = client.devboxes.browsers.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser = response.parse()
+ assert_matches_type(BrowserView, browser, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Runloop) -> None:
+ with client.devboxes.browsers.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser = response.parse()
+ assert_matches_type(BrowserView, browser, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncBrowsers:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncRunloop) -> None:
+ browser = await async_client.devboxes.browsers.create()
+ assert_matches_type(BrowserView, browser, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.devboxes.browsers.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ browser = await response.parse()
+ assert_matches_type(BrowserView, browser, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncRunloop) -> None:
+ async with async_client.devboxes.browsers.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ browser = await response.parse()
+ assert_matches_type(BrowserView, browser, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/devboxes/test_computers.py b/tests/api_resources/devboxes/test_computers.py
new file mode 100644
index 00000000..09b08358
--- /dev/null
+++ b/tests/api_resources/devboxes/test_computers.py
@@ -0,0 +1,391 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from tests.utils import assert_matches_type
+from runloop_api_client import Runloop, AsyncRunloop
+from runloop_api_client.types.devboxes import (
+ ComputerView,
+ ComputerMouseInteractionResponse,
+ ComputerScreenInteractionResponse,
+ ComputerKeyboardInteractionResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestComputers:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Runloop) -> None:
+ computer = client.devboxes.computers.create()
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ @parametrize
+ def test_method_create_with_all_params(self, client: Runloop) -> None:
+ computer = client.devboxes.computers.create(
+ display_dimensions={
+ "display_height_px": 0,
+ "display_width_px": 0,
+ },
+ )
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Runloop) -> None:
+ response = client.devboxes.computers.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Runloop) -> None:
+ with client.devboxes.computers.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_keyboard_interaction(self, client: Runloop) -> None:
+ computer = client.devboxes.computers.keyboard_interaction(
+ id="id",
+ action="key",
+ )
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_method_keyboard_interaction_with_all_params(self, client: Runloop) -> None:
+ computer = client.devboxes.computers.keyboard_interaction(
+ id="id",
+ action="key",
+ text="text",
+ )
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_raw_response_keyboard_interaction(self, client: Runloop) -> None:
+ response = client.devboxes.computers.with_raw_response.keyboard_interaction(
+ id="id",
+ action="key",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_streaming_response_keyboard_interaction(self, client: Runloop) -> None:
+ with client.devboxes.computers.with_streaming_response.keyboard_interaction(
+ id="id",
+ action="key",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_keyboard_interaction(self, client: Runloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.devboxes.computers.with_raw_response.keyboard_interaction(
+ id="",
+ action="key",
+ )
+
+ @parametrize
+ def test_method_mouse_interaction(self, client: Runloop) -> None:
+ computer = client.devboxes.computers.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ )
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_method_mouse_interaction_with_all_params(self, client: Runloop) -> None:
+ computer = client.devboxes.computers.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ coordinate={
+ "x": 0,
+ "y": 0,
+ },
+ )
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_raw_response_mouse_interaction(self, client: Runloop) -> None:
+ response = client.devboxes.computers.with_raw_response.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_streaming_response_mouse_interaction(self, client: Runloop) -> None:
+ with client.devboxes.computers.with_streaming_response.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_mouse_interaction(self, client: Runloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.devboxes.computers.with_raw_response.mouse_interaction(
+ id="",
+ action="mouse_move",
+ )
+
+ @parametrize
+ def test_method_screen_interaction(self, client: Runloop) -> None:
+ computer = client.devboxes.computers.screen_interaction(
+ id="id",
+ action="screenshot",
+ )
+ assert_matches_type(ComputerScreenInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_raw_response_screen_interaction(self, client: Runloop) -> None:
+ response = client.devboxes.computers.with_raw_response.screen_interaction(
+ id="id",
+ action="screenshot",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = response.parse()
+ assert_matches_type(ComputerScreenInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ def test_streaming_response_screen_interaction(self, client: Runloop) -> None:
+ with client.devboxes.computers.with_streaming_response.screen_interaction(
+ id="id",
+ action="screenshot",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = response.parse()
+ assert_matches_type(ComputerScreenInteractionResponse, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_screen_interaction(self, client: Runloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.devboxes.computers.with_raw_response.screen_interaction(
+ id="",
+ action="screenshot",
+ )
+
+
+class TestAsyncComputers:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncRunloop) -> None:
+ computer = await async_client.devboxes.computers.create()
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -> None:
+ computer = await async_client.devboxes.computers.create(
+ display_dimensions={
+ "display_height_px": 0,
+ "display_width_px": 0,
+ },
+ )
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.devboxes.computers.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncRunloop) -> None:
+ async with async_client.devboxes.computers.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert_matches_type(ComputerView, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_keyboard_interaction(self, async_client: AsyncRunloop) -> None:
+ computer = await async_client.devboxes.computers.keyboard_interaction(
+ id="id",
+ action="key",
+ )
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_method_keyboard_interaction_with_all_params(self, async_client: AsyncRunloop) -> None:
+ computer = await async_client.devboxes.computers.keyboard_interaction(
+ id="id",
+ action="key",
+ text="text",
+ )
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_raw_response_keyboard_interaction(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.devboxes.computers.with_raw_response.keyboard_interaction(
+ id="id",
+ action="key",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_keyboard_interaction(self, async_client: AsyncRunloop) -> None:
+ async with async_client.devboxes.computers.with_streaming_response.keyboard_interaction(
+ id="id",
+ action="key",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert_matches_type(ComputerKeyboardInteractionResponse, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_keyboard_interaction(self, async_client: AsyncRunloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.devboxes.computers.with_raw_response.keyboard_interaction(
+ id="",
+ action="key",
+ )
+
+ @parametrize
+ async def test_method_mouse_interaction(self, async_client: AsyncRunloop) -> None:
+ computer = await async_client.devboxes.computers.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ )
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_method_mouse_interaction_with_all_params(self, async_client: AsyncRunloop) -> None:
+ computer = await async_client.devboxes.computers.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ coordinate={
+ "x": 0,
+ "y": 0,
+ },
+ )
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_raw_response_mouse_interaction(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.devboxes.computers.with_raw_response.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_mouse_interaction(self, async_client: AsyncRunloop) -> None:
+ async with async_client.devboxes.computers.with_streaming_response.mouse_interaction(
+ id="id",
+ action="mouse_move",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert_matches_type(ComputerMouseInteractionResponse, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_mouse_interaction(self, async_client: AsyncRunloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.devboxes.computers.with_raw_response.mouse_interaction(
+ id="",
+ action="mouse_move",
+ )
+
+ @parametrize
+ async def test_method_screen_interaction(self, async_client: AsyncRunloop) -> None:
+ computer = await async_client.devboxes.computers.screen_interaction(
+ id="id",
+ action="screenshot",
+ )
+ assert_matches_type(ComputerScreenInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_raw_response_screen_interaction(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.devboxes.computers.with_raw_response.screen_interaction(
+ id="id",
+ action="screenshot",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ computer = await response.parse()
+ assert_matches_type(ComputerScreenInteractionResponse, computer, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_screen_interaction(self, async_client: AsyncRunloop) -> None:
+ async with async_client.devboxes.computers.with_streaming_response.screen_interaction(
+ id="id",
+ action="screenshot",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ computer = await response.parse()
+ assert_matches_type(ComputerScreenInteractionResponse, computer, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_screen_interaction(self, async_client: AsyncRunloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.devboxes.computers.with_raw_response.screen_interaction(
+ id="",
+ action="screenshot",
+ )
diff --git a/tests/api_resources/scenarios/test_runs.py b/tests/api_resources/scenarios/test_runs.py
index 0fa9873e..8a83be2c 100644
--- a/tests/api_resources/scenarios/test_runs.py
+++ b/tests/api_resources/scenarios/test_runs.py
@@ -64,6 +64,7 @@ def test_method_list(self, client: Runloop) -> None:
def test_method_list_with_all_params(self, client: Runloop) -> None:
run = client.scenarios.runs.list(
limit=0,
+ scenario_id=True,
starting_after="starting_after",
)
assert_matches_type(ScenarioRunListView, run, path=["response"])
@@ -215,6 +216,7 @@ async def test_method_list(self, async_client: AsyncRunloop) -> None:
async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> None:
run = await async_client.scenarios.runs.list(
limit=0,
+ scenario_id=True,
starting_after="starting_after",
)
assert_matches_type(ScenarioRunListView, run, path=["response"])
diff --git a/tests/api_resources/test_benchmarks.py b/tests/api_resources/test_benchmarks.py
index 0e1735e0..b3ac18fc 100644
--- a/tests/api_resources/test_benchmarks.py
+++ b/tests/api_resources/test_benchmarks.py
@@ -107,6 +107,7 @@ def test_method_list(self, client: Runloop) -> None:
def test_method_list_with_all_params(self, client: Runloop) -> None:
benchmark = client.benchmarks.list(
limit=0,
+ public=True,
starting_after="starting_after",
)
assert_matches_type(BenchmarkListView, benchmark, path=["response"])
@@ -260,6 +261,7 @@ async def test_method_list(self, async_client: AsyncRunloop) -> None:
async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> None:
benchmark = await async_client.benchmarks.list(
limit=0,
+ public=True,
starting_after="starting_after",
)
assert_matches_type(BenchmarkListView, benchmark, path=["response"])