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