diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d8dc4898..f4c594677 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: permissions: contents: read id-token: write - runs-on: depot-ubuntu-24.04 + runs-on: ${{ github.repository == 'stainless-sdks/runloop-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - uses: actions/checkout@v4 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c09634347..2afb750c5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.56.2" + ".": "0.57.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index e93852be7..6225bdc74 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-feb1c5fb18adf1bfc11f6fc7ee95f08a319ce4a504c34c68dee66f090f69a70c.yml -openapi_spec_hash: 758379882a3c4bf49f3ded6ac065a604 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-2027ff4b25ad2b5574b2ce497f5d0d02ad8804816ffd6b4e36511e2fa955d0cf.yml +openapi_spec_hash: 54a5a26e9c0b179d2f2a532268d3d711 config_hash: b97411af91b8ec0b8b066358c29091b4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 33da86b4b..710321319 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## 0.57.0 (2025-08-27) + +Full Changelog: [v0.56.2...v0.57.0](https://github.com/runloopai/api-client-python/compare/v0.56.2...v0.57.0) + +### Features + +* **api:** api update ([3a5d31a](https://github.com/runloopai/api-client-python/commit/3a5d31a6eafb76cf8013355ba22676945509681f)) +* **api:** api update ([104af9f](https://github.com/runloopai/api-client-python/commit/104af9fd5482701947186669748098b060715748)) + + +### Bug Fixes + +* avoid newer type syntax ([3412f2b](https://github.com/runloopai/api-client-python/commit/3412f2b11594e35ef48e4b283a9306eb645af6b3)) + + +### Chores + +* **internal:** change ci workflow machines ([b01847c](https://github.com/runloopai/api-client-python/commit/b01847caa9adcebfc4447c10c3723451dcb140a1)) +* **internal:** update pyright exclude list ([0da3132](https://github.com/runloopai/api-client-python/commit/0da3132fb19d9e1aac3770415b72fb1b413f3175)) + ## 0.56.2 (2025-08-25) Full Changelog: [v0.56.1-beta...v0.56.2](https://github.com/runloopai/api-client-python/compare/v0.56.1-beta...v0.56.2) diff --git a/pyproject.toml b/pyproject.toml index e81b71342..a3c6e3692 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "runloop_api_client" -version = "0.56.2" +version = "0.57.0" description = "The official Python library for the runloop API" dynamic = ["readme"] license = "MIT" @@ -157,6 +157,7 @@ exclude = [ "_dev", ".venv", ".nox", + ".git", ] reportImplicitOverride = true diff --git a/src/runloop_api_client/_models.py b/src/runloop_api_client/_models.py index b8387ce98..92f7c10bc 100644 --- a/src/runloop_api_client/_models.py +++ b/src/runloop_api_client/_models.py @@ -304,7 +304,7 @@ def model_dump( exclude_none=exclude_none, ) - return cast(dict[str, Any], json_safe(dumped)) if mode == "json" else dumped + return cast("dict[str, Any]", json_safe(dumped)) if mode == "json" else dumped @override def model_dump_json( diff --git a/src/runloop_api_client/_version.py b/src/runloop_api_client/_version.py index 7ae731aba..23715c2d3 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.56.2" # x-release-please-version +__version__ = "0.57.0" # x-release-please-version diff --git a/src/runloop_api_client/resources/blueprints.py b/src/runloop_api_client/resources/blueprints.py index 8d49769f2..1785d512a 100644 --- a/src/runloop_api_client/resources/blueprints.py +++ b/src/runloop_api_client/resources/blueprints.py @@ -77,6 +77,7 @@ def create( dockerfile: Optional[str] | NotGiven = NOT_GIVEN, file_mounts: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, launch_parameters: Optional[LaunchParameters] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, services: Optional[Iterable[blueprint_create_params.Service]] | NotGiven = NOT_GIVEN, system_setup_commands: Optional[List[str]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -108,6 +109,8 @@ def create( 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. @@ -134,6 +137,7 @@ def create( "dockerfile": dockerfile, "file_mounts": file_mounts, "launch_parameters": launch_parameters, + "metadata": metadata, "services": services, "system_setup_commands": system_setup_commands, }, @@ -472,6 +476,7 @@ def preview( dockerfile: Optional[str] | NotGiven = NOT_GIVEN, file_mounts: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, launch_parameters: Optional[LaunchParameters] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, services: Optional[Iterable[blueprint_preview_params.Service]] | NotGiven = NOT_GIVEN, system_setup_commands: Optional[List[str]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -501,6 +506,8 @@ def preview( 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. @@ -527,6 +534,7 @@ def preview( "dockerfile": dockerfile, "file_mounts": file_mounts, "launch_parameters": launch_parameters, + "metadata": metadata, "services": services, "system_setup_commands": system_setup_commands, }, @@ -572,6 +580,7 @@ async def create( dockerfile: Optional[str] | NotGiven = NOT_GIVEN, file_mounts: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, launch_parameters: Optional[LaunchParameters] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, services: Optional[Iterable[blueprint_create_params.Service]] | NotGiven = NOT_GIVEN, system_setup_commands: Optional[List[str]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -603,6 +612,8 @@ async def create( 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. @@ -629,6 +640,7 @@ async def create( "dockerfile": dockerfile, "file_mounts": file_mounts, "launch_parameters": launch_parameters, + "metadata": metadata, "services": services, "system_setup_commands": system_setup_commands, }, @@ -967,6 +979,7 @@ async def preview( dockerfile: Optional[str] | NotGiven = NOT_GIVEN, file_mounts: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, launch_parameters: Optional[LaunchParameters] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, services: Optional[Iterable[blueprint_preview_params.Service]] | NotGiven = NOT_GIVEN, system_setup_commands: Optional[List[str]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -996,6 +1009,8 @@ async def preview( 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. @@ -1022,6 +1037,7 @@ async def preview( "dockerfile": dockerfile, "file_mounts": file_mounts, "launch_parameters": launch_parameters, + "metadata": metadata, "services": services, "system_setup_commands": system_setup_commands, }, diff --git a/src/runloop_api_client/resources/objects.py b/src/runloop_api_client/resources/objects.py index 8f90b1323..56ffb29fe 100644 --- a/src/runloop_api_client/resources/objects.py +++ b/src/runloop_api_client/resources/objects.py @@ -49,28 +49,7 @@ def with_streaming_response(self) -> ObjectsResourceWithStreamingResponse: def create( self, *, - content_type: Literal[ - "UNSPECIFIED", - "TEXT_PLAIN", - "TEXT_HTML", - "TEXT_CSS", - "TEXT_JAVASCRIPT", - "TEXT_YAML", - "TEXT_CSV", - "APPLICATION_JSON", - "APPLICATION_XML", - "APPLICATION_PDF", - "APPLICATION_ZIP", - "APPLICATION_GZIP", - "APPLICATION_TAR", - "APPLICATION_TAR_GZIP", - "APPLICATION_OCTET_STREAM", - "IMAGE_JPEG", - "IMAGE_PNG", - "IMAGE_GIF", - "IMAGE_SVG", - "IMAGE_WEBP", - ], + content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"], name: str, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -433,28 +412,7 @@ def with_streaming_response(self) -> AsyncObjectsResourceWithStreamingResponse: async def create( self, *, - content_type: Literal[ - "UNSPECIFIED", - "TEXT_PLAIN", - "TEXT_HTML", - "TEXT_CSS", - "TEXT_JAVASCRIPT", - "TEXT_YAML", - "TEXT_CSV", - "APPLICATION_JSON", - "APPLICATION_XML", - "APPLICATION_PDF", - "APPLICATION_ZIP", - "APPLICATION_GZIP", - "APPLICATION_TAR", - "APPLICATION_TAR_GZIP", - "APPLICATION_OCTET_STREAM", - "IMAGE_JPEG", - "IMAGE_PNG", - "IMAGE_GIF", - "IMAGE_SVG", - "IMAGE_WEBP", - ], + content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"], name: str, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. diff --git a/src/runloop_api_client/types/blueprint_build_parameters.py b/src/runloop_api_client/types/blueprint_build_parameters.py index 4139526f8..9d6b25504 100644 --- a/src/runloop_api_client/types/blueprint_build_parameters.py +++ b/src/runloop_api_client/types/blueprint_build_parameters.py @@ -62,6 +62,9 @@ class BlueprintBuildParameters(BaseModel): launch_parameters: Optional[LaunchParameters] = None """Parameters to configure your Devbox at launch time.""" + metadata: Optional[Dict[str, str]] = None + """(Optional) User defined metadata for the Blueprint.""" + services: Optional[List[Service]] = None """(Optional) List of containerized services to include in the Blueprint. diff --git a/src/runloop_api_client/types/blueprint_create_params.py b/src/runloop_api_client/types/blueprint_create_params.py index 0beb3d469..5931a8ce4 100644 --- a/src/runloop_api_client/types/blueprint_create_params.py +++ b/src/runloop_api_client/types/blueprint_create_params.py @@ -33,6 +33,9 @@ class BlueprintCreateParams(TypedDict, total=False): launch_parameters: Optional[LaunchParameters] """Parameters to configure your Devbox at launch time.""" + 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. diff --git a/src/runloop_api_client/types/blueprint_preview_params.py b/src/runloop_api_client/types/blueprint_preview_params.py index 11112080f..41c0d9e63 100644 --- a/src/runloop_api_client/types/blueprint_preview_params.py +++ b/src/runloop_api_client/types/blueprint_preview_params.py @@ -33,6 +33,9 @@ class BlueprintPreviewParams(TypedDict, total=False): launch_parameters: Optional[LaunchParameters] """Parameters to configure your Devbox at launch time.""" + 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. diff --git a/src/runloop_api_client/types/object_create_params.py b/src/runloop_api_client/types/object_create_params.py index 52a5af6f9..fe554c188 100644 --- a/src/runloop_api_client/types/object_create_params.py +++ b/src/runloop_api_client/types/object_create_params.py @@ -9,30 +9,7 @@ class ObjectCreateParams(TypedDict, total=False): - content_type: Required[ - Literal[ - "UNSPECIFIED", - "TEXT_PLAIN", - "TEXT_HTML", - "TEXT_CSS", - "TEXT_JAVASCRIPT", - "TEXT_YAML", - "TEXT_CSV", - "APPLICATION_JSON", - "APPLICATION_XML", - "APPLICATION_PDF", - "APPLICATION_ZIP", - "APPLICATION_GZIP", - "APPLICATION_TAR", - "APPLICATION_TAR_GZIP", - "APPLICATION_OCTET_STREAM", - "IMAGE_JPEG", - "IMAGE_PNG", - "IMAGE_GIF", - "IMAGE_SVG", - "IMAGE_WEBP", - ] - ] + content_type: Required[Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"]] """The content type of the Object.""" name: Required[str] diff --git a/src/runloop_api_client/types/object_view.py b/src/runloop_api_client/types/object_view.py index 549e7e8fb..18c7c1d3c 100644 --- a/src/runloop_api_client/types/object_view.py +++ b/src/runloop_api_client/types/object_view.py @@ -12,28 +12,7 @@ class ObjectView(BaseModel): id: str """The unique identifier of the Object.""" - content_type: Literal[ - "UNSPECIFIED", - "TEXT_PLAIN", - "TEXT_HTML", - "TEXT_CSS", - "TEXT_JAVASCRIPT", - "TEXT_YAML", - "TEXT_CSV", - "APPLICATION_JSON", - "APPLICATION_XML", - "APPLICATION_PDF", - "APPLICATION_ZIP", - "APPLICATION_GZIP", - "APPLICATION_TAR", - "APPLICATION_TAR_GZIP", - "APPLICATION_OCTET_STREAM", - "IMAGE_JPEG", - "IMAGE_PNG", - "IMAGE_GIF", - "IMAGE_SVG", - "IMAGE_WEBP", - ] + content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"] """The content type of the Object.""" name: str diff --git a/src/runloop_api_client/types/shared/run_profile.py b/src/runloop_api_client/types/shared/run_profile.py index d107fcc76..21a29ef38 100644 --- a/src/runloop_api_client/types/shared/run_profile.py +++ b/src/runloop_api_client/types/shared/run_profile.py @@ -5,6 +5,7 @@ from pydantic import Field as FieldInfo from ..._models import BaseModel +from .launch_parameters import LaunchParameters __all__ = ["RunProfile"] @@ -17,6 +18,9 @@ class RunProfile(BaseModel): set the environment variable 'DB_PASS' to the value 'DATABASE_PASSWORD_VALUE'. """ + launch_parameters: Optional[LaunchParameters] = FieldInfo(alias="launchParameters", default=None) + """Additional runtime LaunchParameters to apply after the devbox starts.""" + purpose: Optional[str] = None """Purpose of the run.""" diff --git a/src/runloop_api_client/types/shared_params/run_profile.py b/src/runloop_api_client/types/shared_params/run_profile.py index eca72fcd1..20816c36d 100644 --- a/src/runloop_api_client/types/shared_params/run_profile.py +++ b/src/runloop_api_client/types/shared_params/run_profile.py @@ -6,6 +6,7 @@ from typing_extensions import Annotated, TypedDict from ..._utils import PropertyInfo +from .launch_parameters import LaunchParameters __all__ = ["RunProfile"] @@ -18,6 +19,9 @@ class RunProfile(TypedDict, total=False): set the environment variable 'DB_PASS' to the value 'DATABASE_PASSWORD_VALUE'. """ + launch_parameters: Annotated[Optional[LaunchParameters], PropertyInfo(alias="launchParameters")] + """Additional runtime LaunchParameters to apply after the devbox starts.""" + purpose: Optional[str] """Purpose of the run.""" diff --git a/tests/api_resources/test_benchmarks.py b/tests/api_resources/test_benchmarks.py index 5585bf1db..0a40742ee 100644 --- a/tests/api_resources/test_benchmarks.py +++ b/tests/api_resources/test_benchmarks.py @@ -288,6 +288,25 @@ def test_method_start_run_with_all_params(self, client: Runloop) -> None: run_name="run_name", run_profile={ "env_vars": {"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", + }, + }, "purpose": "purpose", "secrets": {"foo": "string"}, }, @@ -590,6 +609,25 @@ async def test_method_start_run_with_all_params(self, async_client: AsyncRunloop run_name="run_name", run_profile={ "env_vars": {"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", + }, + }, "purpose": "purpose", "secrets": {"foo": "string"}, }, diff --git a/tests/api_resources/test_blueprints.py b/tests/api_resources/test_blueprints.py index a72c1beac..0ac239ecb 100644 --- a/tests/api_resources/test_blueprints.py +++ b/tests/api_resources/test_blueprints.py @@ -63,6 +63,7 @@ def test_method_create_with_all_params(self, client: Runloop) -> None: "username": "username", }, }, + metadata={"foo": "string"}, services=[ { "image": "image", @@ -327,6 +328,7 @@ def test_method_preview_with_all_params(self, client: Runloop) -> None: "username": "username", }, }, + metadata={"foo": "string"}, services=[ { "image": "image", @@ -415,6 +417,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) - "username": "username", }, }, + metadata={"foo": "string"}, services=[ { "image": "image", @@ -679,6 +682,7 @@ async def test_method_preview_with_all_params(self, async_client: AsyncRunloop) "username": "username", }, }, + metadata={"foo": "string"}, services=[ { "image": "image", diff --git a/tests/api_resources/test_objects.py b/tests/api_resources/test_objects.py index aa3462a55..cf5a4cd3b 100644 --- a/tests/api_resources/test_objects.py +++ b/tests/api_resources/test_objects.py @@ -24,7 +24,7 @@ class TestObjects: @parametrize def test_method_create(self, client: Runloop) -> None: object_ = client.objects.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", ) assert_matches_type(ObjectView, object_, path=["response"]) @@ -32,7 +32,7 @@ def test_method_create(self, client: Runloop) -> None: @parametrize def test_method_create_with_all_params(self, client: Runloop) -> None: object_ = client.objects.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", metadata={"foo": "string"}, ) @@ -41,7 +41,7 @@ def test_method_create_with_all_params(self, client: Runloop) -> None: @parametrize def test_raw_response_create(self, client: Runloop) -> None: response = client.objects.with_raw_response.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", ) @@ -53,7 +53,7 @@ def test_raw_response_create(self, client: Runloop) -> None: @parametrize def test_streaming_response_create(self, client: Runloop) -> None: with client.objects.with_streaming_response.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", ) as response: assert not response.is_closed @@ -307,7 +307,7 @@ class TestAsyncObjects: @parametrize async def test_method_create(self, async_client: AsyncRunloop) -> None: object_ = await async_client.objects.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", ) assert_matches_type(ObjectView, object_, path=["response"]) @@ -315,7 +315,7 @@ async def test_method_create(self, async_client: AsyncRunloop) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -> None: object_ = await async_client.objects.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", metadata={"foo": "string"}, ) @@ -324,7 +324,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.objects.with_raw_response.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", ) @@ -336,7 +336,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.objects.with_streaming_response.create( - content_type="UNSPECIFIED", + content_type="unspecified", name="name", ) as response: assert not response.is_closed diff --git a/tests/api_resources/test_scenarios.py b/tests/api_resources/test_scenarios.py index a2da71fab..0896213f7 100644 --- a/tests/api_resources/test_scenarios.py +++ b/tests/api_resources/test_scenarios.py @@ -364,6 +364,25 @@ def test_method_start_run_with_all_params(self, client: Runloop) -> None: run_name="run_name", run_profile={ "env_vars": {"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", + }, + }, "purpose": "purpose", "secrets": {"foo": "string"}, }, @@ -743,6 +762,25 @@ async def test_method_start_run_with_all_params(self, async_client: AsyncRunloop run_name="run_name", run_profile={ "env_vars": {"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", + }, + }, "purpose": "purpose", "secrets": {"foo": "string"}, },