From 8d62f4b5018b52f3d813b8f6a1f3e5460b80e368 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 1 Oct 2025 20:07:05 +0000
Subject: [PATCH 1/4] feat(api): api update
---
.stats.yml | 8 +-
api.md | 3 +
.../resources/blueprints.py | 91 +++----------
.../resources/repositories.py | 128 +++++++++++++++++-
src/runloop_api_client/types/__init__.py | 2 +
.../types/blueprint_create_params.py | 72 ++--------
.../types/inspection_source_param.py | 16 +++
.../types/repository_inspect_params.py | 16 +++
tests/api_resources/test_blueprints.py | 64 ++-------
tests/api_resources/test_repositories.py | 95 +++++++++++++
10 files changed, 305 insertions(+), 190 deletions(-)
create mode 100644 src/runloop_api_client/types/inspection_source_param.py
create mode 100644 src/runloop_api_client/types/repository_inspect_params.py
diff --git a/.stats.yml b/.stats.yml
index be3e247e2..f933e2cc8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 90
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-9b2e136aedff0713e8d50d6c53a930cd2c3583dcac1a9fce552cf25bb0d29214.yml
-openapi_spec_hash: 81e1da702f2dfb28bbe1bfab0d5d8cbd
-config_hash: 5b2602a56850cf0d0e50da298d1c6916
+configured_endpoints: 91
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-034d0b86510db8b712b55ac88c1c4a322db2ce84edc632f6d27be1eb4f34fd37.yml
+openapi_spec_hash: 0485ec0d01253b2c1bdab3015370808e
+config_hash: 35e129f39a0c1fd38209b0dafb7c7562
diff --git a/api.md b/api.md
index 0087ec8ea..a1b4c0465 100644
--- a/api.md
+++ b/api.md
@@ -45,12 +45,14 @@ Types:
```python
from runloop_api_client.types import (
+ BlueprintBuildFromInspectionParameters,
BlueprintBuildLog,
BlueprintBuildLogsListView,
BlueprintBuildParameters,
BlueprintListView,
BlueprintPreviewView,
BlueprintView,
+ InspectionSource,
)
```
@@ -298,6 +300,7 @@ Methods:
- client.repositories.retrieve(id) -> RepositoryConnectionView
- client.repositories.list(\*\*params) -> SyncRepositoriesCursorIDPage[RepositoryConnectionView]
- client.repositories.delete(id) -> object
+- client.repositories.inspect(id, \*\*params) -> RepositoryInspectionDetails
- client.repositories.list_inspections(id) -> RepositoryInspectionListView
- client.repositories.refresh(id, \*\*params) -> object
diff --git a/src/runloop_api_client/resources/blueprints.py b/src/runloop_api_client/resources/blueprints.py
index 76ad77a0a..83a4d5c90 100644
--- a/src/runloop_api_client/resources/blueprints.py
+++ b/src/runloop_api_client/resources/blueprints.py
@@ -29,6 +29,7 @@
from ..lib.polling_async import async_poll_until
from ..types.blueprint_view import BlueprintView
from ..types.blueprint_preview_view import BlueprintPreviewView
+from ..types.inspection_source_param import InspectionSourceParam
from ..types.blueprint_build_logs_list_view import BlueprintBuildLogsListView
from ..types.shared_params.launch_parameters import LaunchParameters
from ..types.shared_params.code_mount_parameters import CodeMountParameters
@@ -71,16 +72,11 @@ def with_streaming_response(self) -> BlueprintsResourceWithStreamingResponse:
def create(
self,
*,
+ inspection_source: InspectionSourceParam,
name: str,
- base_blueprint_id: Optional[str] | Omit = omit,
- base_blueprint_name: Optional[str] | Omit = omit,
- build_args: Optional[Dict[str, str]] | Omit = omit,
- code_mounts: Optional[Iterable[CodeMountParameters]] | Omit = omit,
- dockerfile: Optional[str] | Omit = omit,
file_mounts: Optional[Dict[str, str]] | Omit = omit,
launch_parameters: Optional[LaunchParameters] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
- services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
system_setup_commands: Optional[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.
@@ -90,29 +86,16 @@ def create(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> BlueprintView:
- """Starts build of custom defined container Blueprint.
-
- The Blueprint will begin in
- the 'provisioning' step and transition to the 'building' step once it is
- selected off the build queue., Upon build complete it will transition to
- 'building_complete' if the build is successful.
+ """
+ Starts build of custom defined container Blueprint using a RepositoryConnection
+ Inspection as a source container specification.
Args:
- name: Name of the Blueprint.
-
- base_blueprint_id: (Optional) ID of previously built blueprint to use as a base blueprint for this
- build.
-
- base_blueprint_name: (Optional) Name of previously built blueprint to use as a base blueprint for
- this build. When set, this will load the latest successfully built Blueprint
- with the given name. Only one of (base_blueprint_id, base_blueprint_name) should
- be specified.
+ inspection_source: (Optional) Use a RepositoryInspection a source of a Blueprint build. The
+ Dockerfile will be automatically created based on the RepositoryInspection
+ contents.
- build_args: (Optional) Arbitrary Docker build args to pass during build.
-
- code_mounts: A list of code mounts to be included in the Blueprint.
-
- dockerfile: Dockerfile contents to be used to build the Blueprint.
+ name: Name of the Blueprint.
file_mounts: (Optional) Map of paths and file contents to write before setup.
@@ -120,10 +103,6 @@ def create(
metadata: (Optional) User defined metadata for the Blueprint.
- services: (Optional) List of containerized services to include in the Blueprint. These
- services will be pre-pulled during the build phase for optimized startup
- performance.
-
system_setup_commands: A list of commands to run to set up your system.
extra_headers: Send extra headers
@@ -140,16 +119,11 @@ def create(
"/v1/blueprints",
body=maybe_transform(
{
+ "inspection_source": inspection_source,
"name": name,
- "base_blueprint_id": base_blueprint_id,
- "base_blueprint_name": base_blueprint_name,
- "build_args": build_args,
- "code_mounts": code_mounts,
- "dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
"metadata": metadata,
- "services": services,
"system_setup_commands": system_setup_commands,
},
blueprint_create_params.BlueprintCreateParams,
@@ -596,16 +570,11 @@ def with_streaming_response(self) -> AsyncBlueprintsResourceWithStreamingRespons
async def create(
self,
*,
+ inspection_source: InspectionSourceParam,
name: str,
- base_blueprint_id: Optional[str] | Omit = omit,
- base_blueprint_name: Optional[str] | Omit = omit,
- build_args: Optional[Dict[str, str]] | Omit = omit,
- code_mounts: Optional[Iterable[CodeMountParameters]] | Omit = omit,
- dockerfile: Optional[str] | Omit = omit,
file_mounts: Optional[Dict[str, str]] | Omit = omit,
launch_parameters: Optional[LaunchParameters] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
- services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
system_setup_commands: Optional[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.
@@ -615,29 +584,16 @@ async def create(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> BlueprintView:
- """Starts build of custom defined container Blueprint.
-
- The Blueprint will begin in
- the 'provisioning' step and transition to the 'building' step once it is
- selected off the build queue., Upon build complete it will transition to
- 'building_complete' if the build is successful.
+ """
+ Starts build of custom defined container Blueprint using a RepositoryConnection
+ Inspection as a source container specification.
Args:
- name: Name of the Blueprint.
-
- base_blueprint_id: (Optional) ID of previously built blueprint to use as a base blueprint for this
- build.
-
- base_blueprint_name: (Optional) Name of previously built blueprint to use as a base blueprint for
- this build. When set, this will load the latest successfully built Blueprint
- with the given name. Only one of (base_blueprint_id, base_blueprint_name) should
- be specified.
+ inspection_source: (Optional) Use a RepositoryInspection a source of a Blueprint build. The
+ Dockerfile will be automatically created based on the RepositoryInspection
+ contents.
- build_args: (Optional) Arbitrary Docker build args to pass during build.
-
- code_mounts: A list of code mounts to be included in the Blueprint.
-
- dockerfile: Dockerfile contents to be used to build the Blueprint.
+ name: Name of the Blueprint.
file_mounts: (Optional) Map of paths and file contents to write before setup.
@@ -645,10 +601,6 @@ async def create(
metadata: (Optional) User defined metadata for the Blueprint.
- services: (Optional) List of containerized services to include in the Blueprint. These
- services will be pre-pulled during the build phase for optimized startup
- performance.
-
system_setup_commands: A list of commands to run to set up your system.
extra_headers: Send extra headers
@@ -665,16 +617,11 @@ async def create(
"/v1/blueprints",
body=await async_maybe_transform(
{
+ "inspection_source": inspection_source,
"name": name,
- "base_blueprint_id": base_blueprint_id,
- "base_blueprint_name": base_blueprint_name,
- "build_args": build_args,
- "code_mounts": code_mounts,
- "dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
"metadata": metadata,
- "services": services,
"system_setup_commands": system_setup_commands,
},
blueprint_create_params.BlueprintCreateParams,
diff --git a/src/runloop_api_client/resources/repositories.py b/src/runloop_api_client/resources/repositories.py
index 99c484ba1..d11c7e800 100644
--- a/src/runloop_api_client/resources/repositories.py
+++ b/src/runloop_api_client/resources/repositories.py
@@ -6,7 +6,12 @@
import httpx
-from ..types import repository_list_params, repository_create_params, repository_refresh_params
+from ..types import (
+ repository_list_params,
+ repository_create_params,
+ repository_inspect_params,
+ repository_refresh_params,
+)
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -20,6 +25,7 @@
from ..pagination import SyncRepositoriesCursorIDPage, AsyncRepositoriesCursorIDPage
from .._base_client import AsyncPaginator, make_request_options
from ..types.repository_connection_view import RepositoryConnectionView
+from ..types.repository_inspection_details import RepositoryInspectionDetails
from ..types.repository_inspection_list_view import RepositoryInspectionListView
__all__ = ["RepositoriesResource", "AsyncRepositoriesResource"]
@@ -234,6 +240,60 @@ def delete(
cast_to=object,
)
+ def inspect(
+ self,
+ id: str,
+ *,
+ blueprint_id: Optional[str] | Omit = omit,
+ github_auth_token: Optional[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,
+ idempotency_key: str | None = None,
+ ) -> RepositoryInspectionDetails:
+ """
+ Inspect a repository connection by inspecting the specified version including
+ repo's technical stack and developer environment requirements.
+
+ Args:
+ blueprint_id: ID of blueprint to use as base for resulting RepositoryVersion blueprint.
+
+ github_auth_token: GitHub authentication token for accessing private repositories.
+
+ 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/repositories/{id}/inspect",
+ body=maybe_transform(
+ {
+ "blueprint_id": blueprint_id,
+ "github_auth_token": github_auth_token,
+ },
+ repository_inspect_params.RepositoryInspectParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=RepositoryInspectionDetails,
+ )
+
def list_inspections(
self,
id: str,
@@ -532,6 +592,60 @@ async def delete(
cast_to=object,
)
+ async def inspect(
+ self,
+ id: str,
+ *,
+ blueprint_id: Optional[str] | Omit = omit,
+ github_auth_token: Optional[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,
+ idempotency_key: str | None = None,
+ ) -> RepositoryInspectionDetails:
+ """
+ Inspect a repository connection by inspecting the specified version including
+ repo's technical stack and developer environment requirements.
+
+ Args:
+ blueprint_id: ID of blueprint to use as base for resulting RepositoryVersion blueprint.
+
+ github_auth_token: GitHub authentication token for accessing private repositories.
+
+ 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/repositories/{id}/inspect",
+ body=await async_maybe_transform(
+ {
+ "blueprint_id": blueprint_id,
+ "github_auth_token": github_auth_token,
+ },
+ repository_inspect_params.RepositoryInspectParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=RepositoryInspectionDetails,
+ )
+
async def list_inspections(
self,
id: str,
@@ -637,6 +751,9 @@ def __init__(self, repositories: RepositoriesResource) -> None:
self.delete = to_raw_response_wrapper(
repositories.delete,
)
+ self.inspect = to_raw_response_wrapper(
+ repositories.inspect,
+ )
self.list_inspections = to_raw_response_wrapper(
repositories.list_inspections,
)
@@ -661,6 +778,9 @@ def __init__(self, repositories: AsyncRepositoriesResource) -> None:
self.delete = async_to_raw_response_wrapper(
repositories.delete,
)
+ self.inspect = async_to_raw_response_wrapper(
+ repositories.inspect,
+ )
self.list_inspections = async_to_raw_response_wrapper(
repositories.list_inspections,
)
@@ -685,6 +805,9 @@ def __init__(self, repositories: RepositoriesResource) -> None:
self.delete = to_streamed_response_wrapper(
repositories.delete,
)
+ self.inspect = to_streamed_response_wrapper(
+ repositories.inspect,
+ )
self.list_inspections = to_streamed_response_wrapper(
repositories.list_inspections,
)
@@ -709,6 +832,9 @@ def __init__(self, repositories: AsyncRepositoriesResource) -> None:
self.delete = async_to_streamed_response_wrapper(
repositories.delete,
)
+ self.inspect = async_to_streamed_response_wrapper(
+ repositories.inspect,
+ )
self.list_inspections = async_to_streamed_response_wrapper(
repositories.list_inspections,
)
diff --git a/src/runloop_api_client/types/__init__.py b/src/runloop_api_client/types/__init__.py
index d53235820..0e4598ee6 100644
--- a/src/runloop_api_client/types/__init__.py
+++ b/src/runloop_api_client/types/__init__.py
@@ -52,6 +52,7 @@
from .benchmark_run_list_view import BenchmarkRunListView as BenchmarkRunListView
from .benchmark_update_params import BenchmarkUpdateParams as BenchmarkUpdateParams
from .blueprint_create_params import BlueprintCreateParams as BlueprintCreateParams
+from .inspection_source_param import InspectionSourceParam as InspectionSourceParam
from .blueprint_preview_params import BlueprintPreviewParams as BlueprintPreviewParams
from .object_download_url_view import ObjectDownloadURLView as ObjectDownloadURLView
from .repository_create_params import RepositoryCreateParams as RepositoryCreateParams
@@ -59,6 +60,7 @@
from .devbox_snapshot_list_view import DevboxSnapshotListView as DevboxSnapshotListView
from .devbox_upload_file_params import DevboxUploadFileParams as DevboxUploadFileParams
from .object_list_public_params import ObjectListPublicParams as ObjectListPublicParams
+from .repository_inspect_params import RepositoryInspectParams as RepositoryInspectParams
from .repository_refresh_params import RepositoryRefreshParams as RepositoryRefreshParams
from .scenario_start_run_params import ScenarioStartRunParams as ScenarioStartRunParams
from .benchmark_start_run_params import BenchmarkStartRunParams as BenchmarkStartRunParams
diff --git a/src/runloop_api_client/types/blueprint_create_params.py b/src/runloop_api_client/types/blueprint_create_params.py
index 80d32de9a..211bbd58e 100644
--- a/src/runloop_api_client/types/blueprint_create_params.py
+++ b/src/runloop_api_client/types/blueprint_create_params.py
@@ -2,42 +2,26 @@
from __future__ import annotations
-from typing import Dict, Iterable, Optional
+from typing import Dict, Optional
from typing_extensions import Required, TypedDict
from .._types import SequenceNotStr
+from .inspection_source_param import InspectionSourceParam
from .shared_params.launch_parameters import LaunchParameters
-from .shared_params.code_mount_parameters import CodeMountParameters
-__all__ = ["BlueprintCreateParams", "Service", "ServiceCredentials"]
+__all__ = ["BlueprintCreateParams"]
class BlueprintCreateParams(TypedDict, total=False):
- name: Required[str]
- """Name of the Blueprint."""
+ inspection_source: Required[InspectionSourceParam]
+ """(Optional) Use a RepositoryInspection a source of a Blueprint build.
- base_blueprint_id: Optional[str]
+ The Dockerfile will be automatically created based on the RepositoryInspection
+ contents.
"""
- (Optional) ID of previously built blueprint to use as a base blueprint for this
- build.
- """
-
- base_blueprint_name: Optional[str]
- """
- (Optional) Name of previously built blueprint to use as a base blueprint for
- this build. When set, this will load the latest successfully built Blueprint
- with the given name. Only one of (base_blueprint_id, base_blueprint_name) should
- be specified.
- """
-
- build_args: Optional[Dict[str, str]]
- """(Optional) Arbitrary Docker build args to pass during build."""
- code_mounts: Optional[Iterable[CodeMountParameters]]
- """A list of code mounts to be included in the Blueprint."""
-
- dockerfile: Optional[str]
- """Dockerfile contents to be used to build the Blueprint."""
+ name: Required[str]
+ """Name of the Blueprint."""
file_mounts: Optional[Dict[str, str]]
"""(Optional) Map of paths and file contents to write before setup."""
@@ -48,43 +32,5 @@ class BlueprintCreateParams(TypedDict, total=False):
metadata: Optional[Dict[str, str]]
"""(Optional) User defined metadata for the Blueprint."""
- services: Optional[Iterable[Service]]
- """(Optional) List of containerized services to include in the Blueprint.
-
- These services will be pre-pulled during the build phase for optimized startup
- performance.
- """
-
system_setup_commands: Optional[SequenceNotStr[str]]
"""A list of commands to run to set up your system."""
-
-
-class ServiceCredentials(TypedDict, total=False):
- password: Required[str]
- """The password of the container service."""
-
- username: Required[str]
- """The username of the container service."""
-
-
-class Service(TypedDict, total=False):
- image: Required[str]
- """The image of the container service."""
-
- name: Required[str]
- """The name of the container service."""
-
- credentials: Optional[ServiceCredentials]
- """The credentials of the container service."""
-
- env: Optional[Dict[str, str]]
- """The environment variables of the container service."""
-
- options: Optional[str]
- """Additional Docker container create options."""
-
- port_mappings: Optional[SequenceNotStr[str]]
- """The port mappings of the container service.
-
- Port mappings are in the format of :.
- """
diff --git a/src/runloop_api_client/types/inspection_source_param.py b/src/runloop_api_client/types/inspection_source_param.py
new file mode 100644
index 000000000..ba9e7f397
--- /dev/null
+++ b/src/runloop_api_client/types/inspection_source_param.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 Required, TypedDict
+
+__all__ = ["InspectionSourceParam"]
+
+
+class InspectionSourceParam(TypedDict, total=False):
+ inspection_id: Required[str]
+ """The ID of a repository inspection."""
+
+ github_auth_token: Optional[str]
+ """GitHub authentication token for accessing private repositories."""
diff --git a/src/runloop_api_client/types/repository_inspect_params.py b/src/runloop_api_client/types/repository_inspect_params.py
new file mode 100644
index 000000000..c68b4b830
--- /dev/null
+++ b/src/runloop_api_client/types/repository_inspect_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 TypedDict
+
+__all__ = ["RepositoryInspectParams"]
+
+
+class RepositoryInspectParams(TypedDict, total=False):
+ blueprint_id: Optional[str]
+ """ID of blueprint to use as base for resulting RepositoryVersion blueprint."""
+
+ github_auth_token: Optional[str]
+ """GitHub authentication token for accessing private repositories."""
diff --git a/tests/api_resources/test_blueprints.py b/tests/api_resources/test_blueprints.py
index 0e6eb9eba..3a937c1c6 100644
--- a/tests/api_resources/test_blueprints.py
+++ b/tests/api_resources/test_blueprints.py
@@ -25,6 +25,7 @@ class TestBlueprints:
@parametrize
def test_method_create(self, client: Runloop) -> None:
blueprint = client.blueprints.create(
+ inspection_source={"inspection_id": "inspection_id"},
name="name",
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -32,19 +33,11 @@ def test_method_create(self, client: Runloop) -> None:
@parametrize
def test_method_create_with_all_params(self, client: Runloop) -> None:
blueprint = client.blueprints.create(
+ inspection_source={
+ "inspection_id": "inspection_id",
+ "github_auth_token": "github_auth_token",
+ },
name="name",
- base_blueprint_id="base_blueprint_id",
- base_blueprint_name="base_blueprint_name",
- build_args={"foo": "string"},
- code_mounts=[
- {
- "repo_name": "repo_name",
- "repo_owner": "repo_owner",
- "token": "token",
- "install_command": "install_command",
- }
- ],
- dockerfile="dockerfile",
file_mounts={"foo": "string"},
launch_parameters={
"after_idle": {
@@ -66,19 +59,6 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
},
},
metadata={"foo": "string"},
- services=[
- {
- "image": "image",
- "name": "name",
- "credentials": {
- "password": "password",
- "username": "username",
- },
- "env": {"foo": "string"},
- "options": "options",
- "port_mappings": ["string"],
- }
- ],
system_setup_commands=["string"],
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -86,6 +66,7 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
@parametrize
def test_raw_response_create(self, client: Runloop) -> None:
response = client.blueprints.with_raw_response.create(
+ inspection_source={"inspection_id": "inspection_id"},
name="name",
)
@@ -97,6 +78,7 @@ def test_raw_response_create(self, client: Runloop) -> None:
@parametrize
def test_streaming_response_create(self, client: Runloop) -> None:
with client.blueprints.with_streaming_response.create(
+ inspection_source={"inspection_id": "inspection_id"},
name="name",
) as response:
assert not response.is_closed
@@ -383,6 +365,7 @@ class TestAsyncBlueprints:
@parametrize
async def test_method_create(self, async_client: AsyncRunloop) -> None:
blueprint = await async_client.blueprints.create(
+ inspection_source={"inspection_id": "inspection_id"},
name="name",
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -390,19 +373,11 @@ async def test_method_create(self, async_client: AsyncRunloop) -> None:
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -> None:
blueprint = await async_client.blueprints.create(
+ inspection_source={
+ "inspection_id": "inspection_id",
+ "github_auth_token": "github_auth_token",
+ },
name="name",
- base_blueprint_id="base_blueprint_id",
- base_blueprint_name="base_blueprint_name",
- build_args={"foo": "string"},
- code_mounts=[
- {
- "repo_name": "repo_name",
- "repo_owner": "repo_owner",
- "token": "token",
- "install_command": "install_command",
- }
- ],
- dockerfile="dockerfile",
file_mounts={"foo": "string"},
launch_parameters={
"after_idle": {
@@ -424,19 +399,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
},
},
metadata={"foo": "string"},
- services=[
- {
- "image": "image",
- "name": "name",
- "credentials": {
- "password": "password",
- "username": "username",
- },
- "env": {"foo": "string"},
- "options": "options",
- "port_mappings": ["string"],
- }
- ],
system_setup_commands=["string"],
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -444,6 +406,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
@parametrize
async def test_raw_response_create(self, async_client: AsyncRunloop) -> None:
response = await async_client.blueprints.with_raw_response.create(
+ inspection_source={"inspection_id": "inspection_id"},
name="name",
)
@@ -455,6 +418,7 @@ async def test_raw_response_create(self, async_client: AsyncRunloop) -> None:
@parametrize
async def test_streaming_response_create(self, async_client: AsyncRunloop) -> None:
async with async_client.blueprints.with_streaming_response.create(
+ inspection_source={"inspection_id": "inspection_id"},
name="name",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_repositories.py b/tests/api_resources/test_repositories.py
index da723e080..8e31ed986 100644
--- a/tests/api_resources/test_repositories.py
+++ b/tests/api_resources/test_repositories.py
@@ -11,6 +11,7 @@
from runloop_api_client import Runloop, AsyncRunloop
from runloop_api_client.types import (
RepositoryConnectionView,
+ RepositoryInspectionDetails,
RepositoryInspectionListView,
)
from runloop_api_client.pagination import SyncRepositoriesCursorIDPage, AsyncRepositoriesCursorIDPage
@@ -176,6 +177,53 @@ def test_path_params_delete(self, client: Runloop) -> None:
"",
)
+ @parametrize
+ def test_method_inspect(self, client: Runloop) -> None:
+ repository = client.repositories.inspect(
+ id="id",
+ )
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ @parametrize
+ def test_method_inspect_with_all_params(self, client: Runloop) -> None:
+ repository = client.repositories.inspect(
+ id="id",
+ blueprint_id="blueprint_id",
+ github_auth_token="github_auth_token",
+ )
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ @parametrize
+ def test_raw_response_inspect(self, client: Runloop) -> None:
+ response = client.repositories.with_raw_response.inspect(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ repository = response.parse()
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ @parametrize
+ def test_streaming_response_inspect(self, client: Runloop) -> None:
+ with client.repositories.with_streaming_response.inspect(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ repository = response.parse()
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_inspect(self, client: Runloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.repositories.with_raw_response.inspect(
+ id="",
+ )
+
@parametrize
def test_method_list_inspections(self, client: Runloop) -> None:
repository = client.repositories.list_inspections(
@@ -422,6 +470,53 @@ async def test_path_params_delete(self, async_client: AsyncRunloop) -> None:
"",
)
+ @parametrize
+ async def test_method_inspect(self, async_client: AsyncRunloop) -> None:
+ repository = await async_client.repositories.inspect(
+ id="id",
+ )
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ @parametrize
+ async def test_method_inspect_with_all_params(self, async_client: AsyncRunloop) -> None:
+ repository = await async_client.repositories.inspect(
+ id="id",
+ blueprint_id="blueprint_id",
+ github_auth_token="github_auth_token",
+ )
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ @parametrize
+ async def test_raw_response_inspect(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.repositories.with_raw_response.inspect(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ repository = await response.parse()
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_inspect(self, async_client: AsyncRunloop) -> None:
+ async with async_client.repositories.with_streaming_response.inspect(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ repository = await response.parse()
+ assert_matches_type(RepositoryInspectionDetails, repository, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_inspect(self, async_client: AsyncRunloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.repositories.with_raw_response.inspect(
+ id="",
+ )
+
@parametrize
async def test_method_list_inspections(self, async_client: AsyncRunloop) -> None:
repository = await async_client.repositories.list_inspections(
From 59b9486f94c15ec76021ec98db3dad93225be663 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 1 Oct 2025 21:24:59 +0000
Subject: [PATCH 2/4] feat(api): api update
---
.stats.yml | 4 +-
.../resources/blueprints.py | 91 +++++++++++++++----
src/runloop_api_client/types/__init__.py | 1 -
.../types/blueprint_create_params.py | 72 +++++++++++++--
.../types/inspection_source_param.py | 16 ----
tests/api_resources/test_blueprints.py | 64 ++++++++++---
6 files changed, 187 insertions(+), 61 deletions(-)
delete mode 100644 src/runloop_api_client/types/inspection_source_param.py
diff --git a/.stats.yml b/.stats.yml
index f933e2cc8..21c53f96b 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 91
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-034d0b86510db8b712b55ac88c1c4a322db2ce84edc632f6d27be1eb4f34fd37.yml
-openapi_spec_hash: 0485ec0d01253b2c1bdab3015370808e
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-f1d928f705d6771a22fe701dfb8c0c66aabbd0dd6d17e3fa09b8eb3a48259a84.yml
+openapi_spec_hash: 12dc18a4da3f084fee3d2c5f428e1df3
config_hash: 35e129f39a0c1fd38209b0dafb7c7562
diff --git a/src/runloop_api_client/resources/blueprints.py b/src/runloop_api_client/resources/blueprints.py
index 83a4d5c90..76ad77a0a 100644
--- a/src/runloop_api_client/resources/blueprints.py
+++ b/src/runloop_api_client/resources/blueprints.py
@@ -29,7 +29,6 @@
from ..lib.polling_async import async_poll_until
from ..types.blueprint_view import BlueprintView
from ..types.blueprint_preview_view import BlueprintPreviewView
-from ..types.inspection_source_param import InspectionSourceParam
from ..types.blueprint_build_logs_list_view import BlueprintBuildLogsListView
from ..types.shared_params.launch_parameters import LaunchParameters
from ..types.shared_params.code_mount_parameters import CodeMountParameters
@@ -72,11 +71,16 @@ def with_streaming_response(self) -> BlueprintsResourceWithStreamingResponse:
def create(
self,
*,
- inspection_source: InspectionSourceParam,
name: str,
+ base_blueprint_id: Optional[str] | Omit = omit,
+ base_blueprint_name: Optional[str] | Omit = omit,
+ build_args: Optional[Dict[str, str]] | Omit = omit,
+ code_mounts: Optional[Iterable[CodeMountParameters]] | Omit = omit,
+ dockerfile: Optional[str] | Omit = omit,
file_mounts: Optional[Dict[str, str]] | Omit = omit,
launch_parameters: Optional[LaunchParameters] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
system_setup_commands: Optional[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.
@@ -86,23 +90,40 @@ def create(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> BlueprintView:
- """
- Starts build of custom defined container Blueprint using a RepositoryConnection
- Inspection as a source container specification.
+ """Starts build of custom defined container Blueprint.
- Args:
- inspection_source: (Optional) Use a RepositoryInspection a source of a Blueprint build. The
- Dockerfile will be automatically created based on the RepositoryInspection
- contents.
+ The Blueprint will begin in
+ the 'provisioning' step and transition to the 'building' step once it is
+ selected off the build queue., Upon build complete it will transition to
+ 'building_complete' if the build is successful.
+ Args:
name: Name of the Blueprint.
+ base_blueprint_id: (Optional) ID of previously built blueprint to use as a base blueprint for this
+ build.
+
+ base_blueprint_name: (Optional) Name of previously built blueprint to use as a base blueprint for
+ this build. When set, this will load the latest successfully built Blueprint
+ with the given name. Only one of (base_blueprint_id, base_blueprint_name) should
+ be specified.
+
+ build_args: (Optional) Arbitrary Docker build args to pass during build.
+
+ code_mounts: A list of code mounts to be included in the Blueprint.
+
+ dockerfile: Dockerfile contents to be used to build the Blueprint.
+
file_mounts: (Optional) Map of paths and file contents to write before setup.
launch_parameters: Parameters to configure your Devbox at launch time.
metadata: (Optional) User defined metadata for the Blueprint.
+ services: (Optional) List of containerized services to include in the Blueprint. These
+ services will be pre-pulled during the build phase for optimized startup
+ performance.
+
system_setup_commands: A list of commands to run to set up your system.
extra_headers: Send extra headers
@@ -119,11 +140,16 @@ def create(
"/v1/blueprints",
body=maybe_transform(
{
- "inspection_source": inspection_source,
"name": name,
+ "base_blueprint_id": base_blueprint_id,
+ "base_blueprint_name": base_blueprint_name,
+ "build_args": build_args,
+ "code_mounts": code_mounts,
+ "dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
"metadata": metadata,
+ "services": services,
"system_setup_commands": system_setup_commands,
},
blueprint_create_params.BlueprintCreateParams,
@@ -570,11 +596,16 @@ def with_streaming_response(self) -> AsyncBlueprintsResourceWithStreamingRespons
async def create(
self,
*,
- inspection_source: InspectionSourceParam,
name: str,
+ base_blueprint_id: Optional[str] | Omit = omit,
+ base_blueprint_name: Optional[str] | Omit = omit,
+ build_args: Optional[Dict[str, str]] | Omit = omit,
+ code_mounts: Optional[Iterable[CodeMountParameters]] | Omit = omit,
+ dockerfile: Optional[str] | Omit = omit,
file_mounts: Optional[Dict[str, str]] | Omit = omit,
launch_parameters: Optional[LaunchParameters] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
system_setup_commands: Optional[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.
@@ -584,23 +615,40 @@ async def create(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> BlueprintView:
- """
- Starts build of custom defined container Blueprint using a RepositoryConnection
- Inspection as a source container specification.
+ """Starts build of custom defined container Blueprint.
- Args:
- inspection_source: (Optional) Use a RepositoryInspection a source of a Blueprint build. The
- Dockerfile will be automatically created based on the RepositoryInspection
- contents.
+ The Blueprint will begin in
+ the 'provisioning' step and transition to the 'building' step once it is
+ selected off the build queue., Upon build complete it will transition to
+ 'building_complete' if the build is successful.
+ Args:
name: Name of the Blueprint.
+ base_blueprint_id: (Optional) ID of previously built blueprint to use as a base blueprint for this
+ build.
+
+ base_blueprint_name: (Optional) Name of previously built blueprint to use as a base blueprint for
+ this build. When set, this will load the latest successfully built Blueprint
+ with the given name. Only one of (base_blueprint_id, base_blueprint_name) should
+ be specified.
+
+ build_args: (Optional) Arbitrary Docker build args to pass during build.
+
+ code_mounts: A list of code mounts to be included in the Blueprint.
+
+ dockerfile: Dockerfile contents to be used to build the Blueprint.
+
file_mounts: (Optional) Map of paths and file contents to write before setup.
launch_parameters: Parameters to configure your Devbox at launch time.
metadata: (Optional) User defined metadata for the Blueprint.
+ services: (Optional) List of containerized services to include in the Blueprint. These
+ services will be pre-pulled during the build phase for optimized startup
+ performance.
+
system_setup_commands: A list of commands to run to set up your system.
extra_headers: Send extra headers
@@ -617,11 +665,16 @@ async def create(
"/v1/blueprints",
body=await async_maybe_transform(
{
- "inspection_source": inspection_source,
"name": name,
+ "base_blueprint_id": base_blueprint_id,
+ "base_blueprint_name": base_blueprint_name,
+ "build_args": build_args,
+ "code_mounts": code_mounts,
+ "dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
"metadata": metadata,
+ "services": services,
"system_setup_commands": system_setup_commands,
},
blueprint_create_params.BlueprintCreateParams,
diff --git a/src/runloop_api_client/types/__init__.py b/src/runloop_api_client/types/__init__.py
index 0e4598ee6..5dcfbe0fe 100644
--- a/src/runloop_api_client/types/__init__.py
+++ b/src/runloop_api_client/types/__init__.py
@@ -52,7 +52,6 @@
from .benchmark_run_list_view import BenchmarkRunListView as BenchmarkRunListView
from .benchmark_update_params import BenchmarkUpdateParams as BenchmarkUpdateParams
from .blueprint_create_params import BlueprintCreateParams as BlueprintCreateParams
-from .inspection_source_param import InspectionSourceParam as InspectionSourceParam
from .blueprint_preview_params import BlueprintPreviewParams as BlueprintPreviewParams
from .object_download_url_view import ObjectDownloadURLView as ObjectDownloadURLView
from .repository_create_params import RepositoryCreateParams as RepositoryCreateParams
diff --git a/src/runloop_api_client/types/blueprint_create_params.py b/src/runloop_api_client/types/blueprint_create_params.py
index 211bbd58e..80d32de9a 100644
--- a/src/runloop_api_client/types/blueprint_create_params.py
+++ b/src/runloop_api_client/types/blueprint_create_params.py
@@ -2,26 +2,42 @@
from __future__ import annotations
-from typing import Dict, Optional
+from typing import Dict, Iterable, Optional
from typing_extensions import Required, TypedDict
from .._types import SequenceNotStr
-from .inspection_source_param import InspectionSourceParam
from .shared_params.launch_parameters import LaunchParameters
+from .shared_params.code_mount_parameters import CodeMountParameters
-__all__ = ["BlueprintCreateParams"]
+__all__ = ["BlueprintCreateParams", "Service", "ServiceCredentials"]
class BlueprintCreateParams(TypedDict, total=False):
- inspection_source: Required[InspectionSourceParam]
- """(Optional) Use a RepositoryInspection a source of a Blueprint build.
+ name: Required[str]
+ """Name of the Blueprint."""
- The Dockerfile will be automatically created based on the RepositoryInspection
- contents.
+ base_blueprint_id: Optional[str]
+ """
+ (Optional) ID of previously built blueprint to use as a base blueprint for this
+ build.
"""
- name: Required[str]
- """Name of the Blueprint."""
+ base_blueprint_name: Optional[str]
+ """
+ (Optional) Name of previously built blueprint to use as a base blueprint for
+ this build. When set, this will load the latest successfully built Blueprint
+ with the given name. Only one of (base_blueprint_id, base_blueprint_name) should
+ be specified.
+ """
+
+ build_args: Optional[Dict[str, str]]
+ """(Optional) Arbitrary Docker build args to pass during build."""
+
+ code_mounts: Optional[Iterable[CodeMountParameters]]
+ """A list of code mounts to be included in the Blueprint."""
+
+ dockerfile: Optional[str]
+ """Dockerfile contents to be used to build the Blueprint."""
file_mounts: Optional[Dict[str, str]]
"""(Optional) Map of paths and file contents to write before setup."""
@@ -32,5 +48,43 @@ class BlueprintCreateParams(TypedDict, total=False):
metadata: Optional[Dict[str, str]]
"""(Optional) User defined metadata for the Blueprint."""
+ services: Optional[Iterable[Service]]
+ """(Optional) List of containerized services to include in the Blueprint.
+
+ These services will be pre-pulled during the build phase for optimized startup
+ performance.
+ """
+
system_setup_commands: Optional[SequenceNotStr[str]]
"""A list of commands to run to set up your system."""
+
+
+class ServiceCredentials(TypedDict, total=False):
+ password: Required[str]
+ """The password of the container service."""
+
+ username: Required[str]
+ """The username of the container service."""
+
+
+class Service(TypedDict, total=False):
+ image: Required[str]
+ """The image of the container service."""
+
+ name: Required[str]
+ """The name of the container service."""
+
+ credentials: Optional[ServiceCredentials]
+ """The credentials of the container service."""
+
+ env: Optional[Dict[str, str]]
+ """The environment variables of the container service."""
+
+ options: Optional[str]
+ """Additional Docker container create options."""
+
+ port_mappings: Optional[SequenceNotStr[str]]
+ """The port mappings of the container service.
+
+ Port mappings are in the format of :.
+ """
diff --git a/src/runloop_api_client/types/inspection_source_param.py b/src/runloop_api_client/types/inspection_source_param.py
deleted file mode 100644
index ba9e7f397..000000000
--- a/src/runloop_api_client/types/inspection_source_param.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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__ = ["InspectionSourceParam"]
-
-
-class InspectionSourceParam(TypedDict, total=False):
- inspection_id: Required[str]
- """The ID of a repository inspection."""
-
- github_auth_token: Optional[str]
- """GitHub authentication token for accessing private repositories."""
diff --git a/tests/api_resources/test_blueprints.py b/tests/api_resources/test_blueprints.py
index 3a937c1c6..0e6eb9eba 100644
--- a/tests/api_resources/test_blueprints.py
+++ b/tests/api_resources/test_blueprints.py
@@ -25,7 +25,6 @@ class TestBlueprints:
@parametrize
def test_method_create(self, client: Runloop) -> None:
blueprint = client.blueprints.create(
- inspection_source={"inspection_id": "inspection_id"},
name="name",
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -33,11 +32,19 @@ def test_method_create(self, client: Runloop) -> None:
@parametrize
def test_method_create_with_all_params(self, client: Runloop) -> None:
blueprint = client.blueprints.create(
- inspection_source={
- "inspection_id": "inspection_id",
- "github_auth_token": "github_auth_token",
- },
name="name",
+ base_blueprint_id="base_blueprint_id",
+ base_blueprint_name="base_blueprint_name",
+ build_args={"foo": "string"},
+ code_mounts=[
+ {
+ "repo_name": "repo_name",
+ "repo_owner": "repo_owner",
+ "token": "token",
+ "install_command": "install_command",
+ }
+ ],
+ dockerfile="dockerfile",
file_mounts={"foo": "string"},
launch_parameters={
"after_idle": {
@@ -59,6 +66,19 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
},
},
metadata={"foo": "string"},
+ services=[
+ {
+ "image": "image",
+ "name": "name",
+ "credentials": {
+ "password": "password",
+ "username": "username",
+ },
+ "env": {"foo": "string"},
+ "options": "options",
+ "port_mappings": ["string"],
+ }
+ ],
system_setup_commands=["string"],
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -66,7 +86,6 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
@parametrize
def test_raw_response_create(self, client: Runloop) -> None:
response = client.blueprints.with_raw_response.create(
- inspection_source={"inspection_id": "inspection_id"},
name="name",
)
@@ -78,7 +97,6 @@ def test_raw_response_create(self, client: Runloop) -> None:
@parametrize
def test_streaming_response_create(self, client: Runloop) -> None:
with client.blueprints.with_streaming_response.create(
- inspection_source={"inspection_id": "inspection_id"},
name="name",
) as response:
assert not response.is_closed
@@ -365,7 +383,6 @@ class TestAsyncBlueprints:
@parametrize
async def test_method_create(self, async_client: AsyncRunloop) -> None:
blueprint = await async_client.blueprints.create(
- inspection_source={"inspection_id": "inspection_id"},
name="name",
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -373,11 +390,19 @@ async def test_method_create(self, async_client: AsyncRunloop) -> None:
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -> None:
blueprint = await async_client.blueprints.create(
- inspection_source={
- "inspection_id": "inspection_id",
- "github_auth_token": "github_auth_token",
- },
name="name",
+ base_blueprint_id="base_blueprint_id",
+ base_blueprint_name="base_blueprint_name",
+ build_args={"foo": "string"},
+ code_mounts=[
+ {
+ "repo_name": "repo_name",
+ "repo_owner": "repo_owner",
+ "token": "token",
+ "install_command": "install_command",
+ }
+ ],
+ dockerfile="dockerfile",
file_mounts={"foo": "string"},
launch_parameters={
"after_idle": {
@@ -399,6 +424,19 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
},
},
metadata={"foo": "string"},
+ services=[
+ {
+ "image": "image",
+ "name": "name",
+ "credentials": {
+ "password": "password",
+ "username": "username",
+ },
+ "env": {"foo": "string"},
+ "options": "options",
+ "port_mappings": ["string"],
+ }
+ ],
system_setup_commands=["string"],
)
assert_matches_type(BlueprintView, blueprint, path=["response"])
@@ -406,7 +444,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
@parametrize
async def test_raw_response_create(self, async_client: AsyncRunloop) -> None:
response = await async_client.blueprints.with_raw_response.create(
- inspection_source={"inspection_id": "inspection_id"},
name="name",
)
@@ -418,7 +455,6 @@ async def test_raw_response_create(self, async_client: AsyncRunloop) -> None:
@parametrize
async def test_streaming_response_create(self, async_client: AsyncRunloop) -> None:
async with async_client.blueprints.with_streaming_response.create(
- inspection_source={"inspection_id": "inspection_id"},
name="name",
) as response:
assert not response.is_closed
From a2ed6d7530f8ea05f600713163ac646989426a65 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 1 Oct 2025 22:01:51 +0000
Subject: [PATCH 3/4] feat(api): api update
---
.stats.yml | 4 +-
api.md | 1 +
.../resources/blueprints.py | 152 ++++++++++++++++++
src/runloop_api_client/types/__init__.py | 4 +
...blueprint_create_from_inspection_params.py | 36 +++++
.../types/inspection_source_param.py | 16 ++
tests/api_resources/test_blueprints.py | 134 +++++++++++++++
7 files changed, 345 insertions(+), 2 deletions(-)
create mode 100644 src/runloop_api_client/types/blueprint_create_from_inspection_params.py
create mode 100644 src/runloop_api_client/types/inspection_source_param.py
diff --git a/.stats.yml b/.stats.yml
index 21c53f96b..32058a67e 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 91
+configured_endpoints: 92
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-f1d928f705d6771a22fe701dfb8c0c66aabbd0dd6d17e3fa09b8eb3a48259a84.yml
openapi_spec_hash: 12dc18a4da3f084fee3d2c5f428e1df3
-config_hash: 35e129f39a0c1fd38209b0dafb7c7562
+config_hash: f9f7bc60c36f103c77333d9149cd3e46
diff --git a/api.md b/api.md
index a1b4c0465..ac46b0558 100644
--- a/api.md
+++ b/api.md
@@ -63,6 +63,7 @@ Methods:
- client.blueprints.retrieve(id) -> BlueprintView
- client.blueprints.list(\*\*params) -> SyncBlueprintsCursorIDPage[BlueprintView]
- client.blueprints.delete(id) -> object
+- client.blueprints.create_from_inspection(\*\*params) -> BlueprintView
- client.blueprints.list_public(\*\*params) -> SyncBlueprintsCursorIDPage[BlueprintView]
- client.blueprints.logs(id) -> BlueprintBuildLogsListView
- client.blueprints.preview(\*\*params) -> BlueprintPreviewView
diff --git a/src/runloop_api_client/resources/blueprints.py b/src/runloop_api_client/resources/blueprints.py
index 76ad77a0a..a4b379e4f 100644
--- a/src/runloop_api_client/resources/blueprints.py
+++ b/src/runloop_api_client/resources/blueprints.py
@@ -11,6 +11,7 @@
blueprint_create_params,
blueprint_preview_params,
blueprint_list_public_params,
+ blueprint_create_from_inspection_params,
)
from .._types import NOT_GIVEN, Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from .._utils import maybe_transform, async_maybe_transform
@@ -29,6 +30,7 @@
from ..lib.polling_async import async_poll_until
from ..types.blueprint_view import BlueprintView
from ..types.blueprint_preview_view import BlueprintPreviewView
+from ..types.inspection_source_param import InspectionSourceParam
from ..types.blueprint_build_logs_list_view import BlueprintBuildLogsListView
from ..types.shared_params.launch_parameters import LaunchParameters
from ..types.shared_params.code_mount_parameters import CodeMountParameters
@@ -394,6 +396,75 @@ def delete(
cast_to=object,
)
+ def create_from_inspection(
+ self,
+ *,
+ inspection_source: InspectionSourceParam,
+ name: str,
+ file_mounts: Optional[Dict[str, str]] | Omit = omit,
+ launch_parameters: Optional[LaunchParameters] | Omit = omit,
+ metadata: Optional[Dict[str, str]] | Omit = omit,
+ system_setup_commands: Optional[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,
+ idempotency_key: str | None = None,
+ ) -> BlueprintView:
+ """
+ Starts build of custom defined container Blueprint using a RepositoryConnection
+ Inspection as a source container specification.
+
+ Args:
+ inspection_source: (Optional) Use a RepositoryInspection a source of a Blueprint build. The
+ Dockerfile will be automatically created based on the RepositoryInspection
+ contents.
+
+ name: Name of the Blueprint.
+
+ file_mounts: (Optional) Map of paths and file contents to write before setup.
+
+ launch_parameters: Parameters to configure your Devbox at launch time.
+
+ metadata: (Optional) User defined metadata for the Blueprint.
+
+ system_setup_commands: A list of commands to run to set up your system.
+
+ 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/blueprints/create_from_inspection",
+ body=maybe_transform(
+ {
+ "inspection_source": inspection_source,
+ "name": name,
+ "file_mounts": file_mounts,
+ "launch_parameters": launch_parameters,
+ "metadata": metadata,
+ "system_setup_commands": system_setup_commands,
+ },
+ blueprint_create_from_inspection_params.BlueprintCreateFromInspectionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=BlueprintView,
+ )
+
def list_public(
self,
*,
@@ -919,6 +990,75 @@ async def delete(
cast_to=object,
)
+ async def create_from_inspection(
+ self,
+ *,
+ inspection_source: InspectionSourceParam,
+ name: str,
+ file_mounts: Optional[Dict[str, str]] | Omit = omit,
+ launch_parameters: Optional[LaunchParameters] | Omit = omit,
+ metadata: Optional[Dict[str, str]] | Omit = omit,
+ system_setup_commands: Optional[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,
+ idempotency_key: str | None = None,
+ ) -> BlueprintView:
+ """
+ Starts build of custom defined container Blueprint using a RepositoryConnection
+ Inspection as a source container specification.
+
+ Args:
+ inspection_source: (Optional) Use a RepositoryInspection a source of a Blueprint build. The
+ Dockerfile will be automatically created based on the RepositoryInspection
+ contents.
+
+ name: Name of the Blueprint.
+
+ file_mounts: (Optional) Map of paths and file contents to write before setup.
+
+ launch_parameters: Parameters to configure your Devbox at launch time.
+
+ metadata: (Optional) User defined metadata for the Blueprint.
+
+ system_setup_commands: A list of commands to run to set up your system.
+
+ 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/blueprints/create_from_inspection",
+ body=await async_maybe_transform(
+ {
+ "inspection_source": inspection_source,
+ "name": name,
+ "file_mounts": file_mounts,
+ "launch_parameters": launch_parameters,
+ "metadata": metadata,
+ "system_setup_commands": system_setup_commands,
+ },
+ blueprint_create_from_inspection_params.BlueprintCreateFromInspectionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=BlueprintView,
+ )
+
def list_public(
self,
*,
@@ -1114,6 +1254,9 @@ def __init__(self, blueprints: BlueprintsResource) -> None:
self.delete = to_raw_response_wrapper(
blueprints.delete,
)
+ self.create_from_inspection = to_raw_response_wrapper(
+ blueprints.create_from_inspection,
+ )
self.list_public = to_raw_response_wrapper(
blueprints.list_public,
)
@@ -1141,6 +1284,9 @@ def __init__(self, blueprints: AsyncBlueprintsResource) -> None:
self.delete = async_to_raw_response_wrapper(
blueprints.delete,
)
+ self.create_from_inspection = async_to_raw_response_wrapper(
+ blueprints.create_from_inspection,
+ )
self.list_public = async_to_raw_response_wrapper(
blueprints.list_public,
)
@@ -1168,6 +1314,9 @@ def __init__(self, blueprints: BlueprintsResource) -> None:
self.delete = to_streamed_response_wrapper(
blueprints.delete,
)
+ self.create_from_inspection = to_streamed_response_wrapper(
+ blueprints.create_from_inspection,
+ )
self.list_public = to_streamed_response_wrapper(
blueprints.list_public,
)
@@ -1195,6 +1344,9 @@ def __init__(self, blueprints: AsyncBlueprintsResource) -> None:
self.delete = async_to_streamed_response_wrapper(
blueprints.delete,
)
+ self.create_from_inspection = async_to_streamed_response_wrapper(
+ blueprints.create_from_inspection,
+ )
self.list_public = async_to_streamed_response_wrapper(
blueprints.list_public,
)
diff --git a/src/runloop_api_client/types/__init__.py b/src/runloop_api_client/types/__init__.py
index 5dcfbe0fe..efffa52f1 100644
--- a/src/runloop_api_client/types/__init__.py
+++ b/src/runloop_api_client/types/__init__.py
@@ -52,6 +52,7 @@
from .benchmark_run_list_view import BenchmarkRunListView as BenchmarkRunListView
from .benchmark_update_params import BenchmarkUpdateParams as BenchmarkUpdateParams
from .blueprint_create_params import BlueprintCreateParams as BlueprintCreateParams
+from .inspection_source_param import InspectionSourceParam as InspectionSourceParam
from .blueprint_preview_params import BlueprintPreviewParams as BlueprintPreviewParams
from .object_download_url_view import ObjectDownloadURLView as ObjectDownloadURLView
from .repository_create_params import RepositoryCreateParams as RepositoryCreateParams
@@ -94,3 +95,6 @@
from .devbox_write_file_contents_params import DevboxWriteFileContentsParams as DevboxWriteFileContentsParams
from .devbox_async_execution_detail_view import DevboxAsyncExecutionDetailView as DevboxAsyncExecutionDetailView
from .devbox_read_file_contents_response import DevboxReadFileContentsResponse as DevboxReadFileContentsResponse
+from .blueprint_create_from_inspection_params import (
+ BlueprintCreateFromInspectionParams as BlueprintCreateFromInspectionParams,
+)
diff --git a/src/runloop_api_client/types/blueprint_create_from_inspection_params.py b/src/runloop_api_client/types/blueprint_create_from_inspection_params.py
new file mode 100644
index 000000000..402bbb4db
--- /dev/null
+++ b/src/runloop_api_client/types/blueprint_create_from_inspection_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 Dict, Optional
+from typing_extensions import Required, TypedDict
+
+from .._types import SequenceNotStr
+from .inspection_source_param import InspectionSourceParam
+from .shared_params.launch_parameters import LaunchParameters
+
+__all__ = ["BlueprintCreateFromInspectionParams"]
+
+
+class BlueprintCreateFromInspectionParams(TypedDict, total=False):
+ inspection_source: Required[InspectionSourceParam]
+ """(Optional) Use a RepositoryInspection a source of a Blueprint build.
+
+ The Dockerfile will be automatically created based on the RepositoryInspection
+ contents.
+ """
+
+ name: Required[str]
+ """Name of the Blueprint."""
+
+ file_mounts: Optional[Dict[str, str]]
+ """(Optional) Map of paths and file contents to write before setup."""
+
+ launch_parameters: Optional[LaunchParameters]
+ """Parameters to configure your Devbox at launch time."""
+
+ metadata: Optional[Dict[str, str]]
+ """(Optional) User defined metadata for the Blueprint."""
+
+ system_setup_commands: Optional[SequenceNotStr[str]]
+ """A list of commands to run to set up your system."""
diff --git a/src/runloop_api_client/types/inspection_source_param.py b/src/runloop_api_client/types/inspection_source_param.py
new file mode 100644
index 000000000..ba9e7f397
--- /dev/null
+++ b/src/runloop_api_client/types/inspection_source_param.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 Required, TypedDict
+
+__all__ = ["InspectionSourceParam"]
+
+
+class InspectionSourceParam(TypedDict, total=False):
+ inspection_id: Required[str]
+ """The ID of a repository inspection."""
+
+ github_auth_token: Optional[str]
+ """GitHub authentication token for accessing private repositories."""
diff --git a/tests/api_resources/test_blueprints.py b/tests/api_resources/test_blueprints.py
index 0e6eb9eba..4c34f9b4e 100644
--- a/tests/api_resources/test_blueprints.py
+++ b/tests/api_resources/test_blueprints.py
@@ -217,6 +217,73 @@ def test_path_params_delete(self, client: Runloop) -> None:
"",
)
+ @parametrize
+ def test_method_create_from_inspection(self, client: Runloop) -> None:
+ blueprint = client.blueprints.create_from_inspection(
+ inspection_source={"inspection_id": "inspection_id"},
+ name="name",
+ )
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ @parametrize
+ def test_method_create_from_inspection_with_all_params(self, client: Runloop) -> None:
+ blueprint = client.blueprints.create_from_inspection(
+ inspection_source={
+ "inspection_id": "inspection_id",
+ "github_auth_token": "github_auth_token",
+ },
+ name="name",
+ file_mounts={"foo": "string"},
+ launch_parameters={
+ "after_idle": {
+ "idle_time_seconds": 0,
+ "on_idle": "shutdown",
+ },
+ "architecture": "x86_64",
+ "available_ports": [0],
+ "custom_cpu_cores": 0,
+ "custom_disk_size": 0,
+ "custom_gb_memory": 0,
+ "keep_alive_time_seconds": 0,
+ "launch_commands": ["string"],
+ "required_services": ["string"],
+ "resource_size_request": "X_SMALL",
+ "user_parameters": {
+ "uid": 0,
+ "username": "username",
+ },
+ },
+ metadata={"foo": "string"},
+ system_setup_commands=["string"],
+ )
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ @parametrize
+ def test_raw_response_create_from_inspection(self, client: Runloop) -> None:
+ response = client.blueprints.with_raw_response.create_from_inspection(
+ inspection_source={"inspection_id": "inspection_id"},
+ name="name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ blueprint = response.parse()
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create_from_inspection(self, client: Runloop) -> None:
+ with client.blueprints.with_streaming_response.create_from_inspection(
+ inspection_source={"inspection_id": "inspection_id"},
+ name="name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ blueprint = response.parse()
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_list_public(self, client: Runloop) -> None:
blueprint = client.blueprints.list_public()
@@ -575,6 +642,73 @@ async def test_path_params_delete(self, async_client: AsyncRunloop) -> None:
"",
)
+ @parametrize
+ async def test_method_create_from_inspection(self, async_client: AsyncRunloop) -> None:
+ blueprint = await async_client.blueprints.create_from_inspection(
+ inspection_source={"inspection_id": "inspection_id"},
+ name="name",
+ )
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ @parametrize
+ async def test_method_create_from_inspection_with_all_params(self, async_client: AsyncRunloop) -> None:
+ blueprint = await async_client.blueprints.create_from_inspection(
+ inspection_source={
+ "inspection_id": "inspection_id",
+ "github_auth_token": "github_auth_token",
+ },
+ name="name",
+ file_mounts={"foo": "string"},
+ launch_parameters={
+ "after_idle": {
+ "idle_time_seconds": 0,
+ "on_idle": "shutdown",
+ },
+ "architecture": "x86_64",
+ "available_ports": [0],
+ "custom_cpu_cores": 0,
+ "custom_disk_size": 0,
+ "custom_gb_memory": 0,
+ "keep_alive_time_seconds": 0,
+ "launch_commands": ["string"],
+ "required_services": ["string"],
+ "resource_size_request": "X_SMALL",
+ "user_parameters": {
+ "uid": 0,
+ "username": "username",
+ },
+ },
+ metadata={"foo": "string"},
+ system_setup_commands=["string"],
+ )
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create_from_inspection(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.blueprints.with_raw_response.create_from_inspection(
+ inspection_source={"inspection_id": "inspection_id"},
+ name="name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ blueprint = await response.parse()
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create_from_inspection(self, async_client: AsyncRunloop) -> None:
+ async with async_client.blueprints.with_streaming_response.create_from_inspection(
+ inspection_source={"inspection_id": "inspection_id"},
+ name="name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ blueprint = await response.parse()
+ assert_matches_type(BlueprintView, blueprint, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_list_public(self, async_client: AsyncRunloop) -> None:
blueprint = await async_client.blueprints.list_public()
From b19dd2a96b2659c14cb22c15a4fec424ef61c67e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 1 Oct 2025 22:02:09 +0000
Subject: [PATCH 4/4] release: 0.62.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 10 ++++++++++
pyproject.toml | 2 +-
src/runloop_api_client/_version.py | 2 +-
4 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index f7e971ead..fdce87245 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.61.0"
+ ".": "0.62.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c797f9ef9..cc1f0550e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## 0.62.0 (2025-10-01)
+
+Full Changelog: [v0.61.0...v0.62.0](https://github.com/runloopai/api-client-python/compare/v0.61.0...v0.62.0)
+
+### Features
+
+* **api:** api update ([a2ed6d7](https://github.com/runloopai/api-client-python/commit/a2ed6d7530f8ea05f600713163ac646989426a65))
+* **api:** api update ([59b9486](https://github.com/runloopai/api-client-python/commit/59b9486f94c15ec76021ec98db3dad93225be663))
+* **api:** api update ([8d62f4b](https://github.com/runloopai/api-client-python/commit/8d62f4b5018b52f3d813b8f6a1f3e5460b80e368))
+
## 0.61.0 (2025-09-29)
Full Changelog: [v0.60.1...v0.61.0](https://github.com/runloopai/api-client-python/compare/v0.60.1...v0.61.0)
diff --git a/pyproject.toml b/pyproject.toml
index 234678c7e..a1dea4bcb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "runloop_api_client"
-version = "0.61.0"
+version = "0.62.0"
description = "The official Python library for the runloop API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/runloop_api_client/_version.py b/src/runloop_api_client/_version.py
index 16da2086a..628c89ebc 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.61.0" # x-release-please-version
+__version__ = "0.62.0" # x-release-please-version