From d67abf1c52a089e192987a261e69219d60514bc3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 19 Nov 2025 00:17:30 +0000
Subject: [PATCH 01/11] chore(package): drop Python 3.8 support
From a52802a6d12d96c3bf4bd670e77c9ec50d08b459 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 11 Nov 2025 03:33:41 +0000
Subject: [PATCH 02/11] fix: compat with Python 3.14
---
src/runloop_api_client/_models.py | 11 ++++++++---
tests/test_models.py | 8 ++++----
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/runloop_api_client/_models.py b/src/runloop_api_client/_models.py
index 76456a237..58f4c89df 100644
--- a/src/runloop_api_client/_models.py
+++ b/src/runloop_api_client/_models.py
@@ -2,6 +2,7 @@
import os
import inspect
+import weakref
from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast
from datetime import date, datetime
from typing_extensions import (
@@ -573,6 +574,9 @@ class CachedDiscriminatorType(Protocol):
__discriminator__: DiscriminatorDetails
+DISCRIMINATOR_CACHE: weakref.WeakKeyDictionary[type, DiscriminatorDetails] = weakref.WeakKeyDictionary()
+
+
class DiscriminatorDetails:
field_name: str
"""The name of the discriminator field in the variant class, e.g.
@@ -615,8 +619,9 @@ def __init__(
def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None:
- if isinstance(union, CachedDiscriminatorType):
- return union.__discriminator__
+ cached = DISCRIMINATOR_CACHE.get(union)
+ if cached is not None:
+ return cached
discriminator_field_name: str | None = None
@@ -669,7 +674,7 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any,
discriminator_field=discriminator_field_name,
discriminator_alias=discriminator_alias,
)
- cast(CachedDiscriminatorType, union).__discriminator__ = details
+ DISCRIMINATOR_CACHE.setdefault(union, details)
return details
diff --git a/tests/test_models.py b/tests/test_models.py
index 87683d2ad..aac33d2e4 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -9,7 +9,7 @@
from runloop_api_client._utils import PropertyInfo
from runloop_api_client._compat import PYDANTIC_V1, parse_obj, model_dump, model_json
-from runloop_api_client._models import BaseModel, construct_type
+from runloop_api_client._models import DISCRIMINATOR_CACHE, BaseModel, construct_type
class BasicModel(BaseModel):
@@ -809,7 +809,7 @@ class B(BaseModel):
UnionType = cast(Any, Union[A, B])
- assert not hasattr(UnionType, "__discriminator__")
+ assert not DISCRIMINATOR_CACHE.get(UnionType)
m = construct_type(
value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")])
@@ -818,7 +818,7 @@ class B(BaseModel):
assert m.type == "b"
assert m.data == "foo" # type: ignore[comparison-overlap]
- discriminator = UnionType.__discriminator__
+ discriminator = DISCRIMINATOR_CACHE.get(UnionType)
assert discriminator is not None
m = construct_type(
@@ -830,7 +830,7 @@ class B(BaseModel):
# if the discriminator details object stays the same between invocations then
# we hit the cache
- assert UnionType.__discriminator__ is discriminator
+ assert DISCRIMINATOR_CACHE.get(UnionType) is discriminator
@pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1")
From 78449be80b3b3f32c14b3fe12909be1d1ea6c1aa Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 11 Nov 2025 21:43:45 +0000
Subject: [PATCH 03/11] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 0ffcd7329..a2fbbe5eb 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 94
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-91cec4aeec2421487d5eeece4804ae3b8b47e22bdbb9fc7460feb64a8c10e42f.yml
-openapi_spec_hash: 3d8d782e2450d46b8ce6573bad488ea1
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-eb33a5a2af905766647a4cf900026240c83d244c67c7a92dc25c453b4e2ca9d6.yml
+openapi_spec_hash: ed79fe718b145466c229630c47943a9e
config_hash: 95facb8cef59b5a1b05763b871bf6a4b
From ee672fdf0881b6dcdf46638821862f27206f8fa9 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 11 Nov 2025 22:48:07 +0000
Subject: [PATCH 04/11] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index a2fbbe5eb..f5090dac7 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 94
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-eb33a5a2af905766647a4cf900026240c83d244c67c7a92dc25c453b4e2ca9d6.yml
-openapi_spec_hash: ed79fe718b145466c229630c47943a9e
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-4f5fe47eea7a16fba1ba473532c7cb9687a113cf97e7b92bac014bca728f9505.yml
+openapi_spec_hash: ae55e0436d54e239a548e245fd19a863
config_hash: 95facb8cef59b5a1b05763b871bf6a4b
From 50340b20148f72cb645bba0bafde6f902e063425 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 12 Nov 2025 03:28:36 +0000
Subject: [PATCH 05/11] fix(compat): update signatures of `model_dump` and
`model_dump_json` for Pydantic v1
---
src/runloop_api_client/_models.py | 41 ++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/src/runloop_api_client/_models.py b/src/runloop_api_client/_models.py
index 58f4c89df..3fcf41040 100644
--- a/src/runloop_api_client/_models.py
+++ b/src/runloop_api_client/_models.py
@@ -257,15 +257,16 @@ def model_dump(
mode: Literal["json", "python"] | str = "python",
include: IncEx | None = None,
exclude: IncEx | None = None,
+ context: Any | None = None,
by_alias: bool | None = None,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
+ exclude_computed_fields: bool = False,
round_trip: bool = False,
warnings: bool | Literal["none", "warn", "error"] = True,
- context: dict[str, Any] | None = None,
- serialize_as_any: bool = False,
fallback: Callable[[Any], Any] | None = None,
+ serialize_as_any: bool = False,
) -> dict[str, Any]:
"""Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump
@@ -273,16 +274,24 @@ def model_dump(
Args:
mode: The mode in which `to_python` should run.
- If mode is 'json', the dictionary will only contain JSON serializable types.
- If mode is 'python', the dictionary may contain any Python objects.
- include: A list of fields to include in the output.
- exclude: A list of fields to exclude from the output.
+ If mode is 'json', the output will only contain JSON serializable types.
+ If mode is 'python', the output may contain non-JSON-serializable Python objects.
+ include: A set of fields to include in the output.
+ exclude: A set of fields to exclude from the output.
+ context: Additional context to pass to the serializer.
by_alias: Whether to use the field's alias in the dictionary key if defined.
- exclude_unset: Whether to exclude fields that are unset or None from the output.
- exclude_defaults: Whether to exclude fields that are set to their default value from the output.
- exclude_none: Whether to exclude fields that have a value of `None` from the output.
- round_trip: Whether to enable serialization and deserialization round-trip support.
- warnings: Whether to log warnings when invalid fields are encountered.
+ exclude_unset: Whether to exclude fields that have not been explicitly set.
+ exclude_defaults: Whether to exclude fields that are set to their default value.
+ exclude_none: Whether to exclude fields that have a value of `None`.
+ exclude_computed_fields: Whether to exclude computed fields.
+ While this can be useful for round-tripping, it is usually recommended to use the dedicated
+ `round_trip` parameter instead.
+ round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
+ warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors,
+ "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].
+ fallback: A function to call when an unknown value is encountered. If not provided,
+ a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised.
+ serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
Returns:
A dictionary representation of the model.
@@ -299,6 +308,8 @@ def model_dump(
raise ValueError("serialize_as_any is only supported in Pydantic v2")
if fallback is not None:
raise ValueError("fallback is only supported in Pydantic v2")
+ if exclude_computed_fields != False:
+ raise ValueError("exclude_computed_fields is only supported in Pydantic v2")
dumped = super().dict( # pyright: ignore[reportDeprecated]
include=include,
exclude=exclude,
@@ -315,15 +326,17 @@ def model_dump_json(
self,
*,
indent: int | None = None,
+ ensure_ascii: bool = False,
include: IncEx | None = None,
exclude: IncEx | None = None,
+ context: Any | None = None,
by_alias: bool | None = None,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
+ exclude_computed_fields: bool = False,
round_trip: bool = False,
warnings: bool | Literal["none", "warn", "error"] = True,
- context: dict[str, Any] | None = None,
fallback: Callable[[Any], Any] | None = None,
serialize_as_any: bool = False,
) -> str:
@@ -355,6 +368,10 @@ def model_dump_json(
raise ValueError("serialize_as_any is only supported in Pydantic v2")
if fallback is not None:
raise ValueError("fallback is only supported in Pydantic v2")
+ if ensure_ascii != False:
+ raise ValueError("ensure_ascii is only supported in Pydantic v2")
+ if exclude_computed_fields != False:
+ raise ValueError("exclude_computed_fields is only supported in Pydantic v2")
return super().json( # type: ignore[reportDeprecated]
indent=indent,
include=include,
From ce55350d81f7f5ba3a3aff8faea88c0e1366cea9 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 12 Nov 2025 18:58:23 +0000
Subject: [PATCH 06/11] feat(blueprints): prevent deletion of blueprints with
dependent snapshots
---
.stats.yml | 8 +-
api.md | 15 +
src/runloop_api_client/_client.py | 39 +-
src/runloop_api_client/pagination.py | 75 ++++
src/runloop_api_client/resources/__init__.py | 14 +
src/runloop_api_client/resources/agents.py | 415 ++++++++++++++++++
.../resources/blueprints.py | 14 +-
.../resources/devboxes/devboxes.py | 16 +-
.../resources/devboxes/disk_snapshots.py | 16 +-
src/runloop_api_client/types/__init__.py | 5 +
.../types/agent_create_params.py | 18 +
.../types/agent_list_params.py | 24 +
.../types/agent_list_view.py | 22 +
src/runloop_api_client/types/agent_view.py | 22 +
.../devbox_list_disk_snapshots_params.py | 3 +
.../types/devbox_snapshot_view.py | 3 +
.../devboxes/disk_snapshot_list_params.py | 3 +
.../types/shared/__init__.py | 1 +
.../types/shared/agent_mount_parameters.py | 5 +-
.../types/shared/agent_source.py | 62 +++
.../types/shared_params/__init__.py | 1 +
.../shared_params/agent_mount_parameters.py | 5 +-
.../types/shared_params/agent_source.py | 65 +++
.../devboxes/test_disk_snapshots.py | 2 +
tests/api_resources/test_agents.py | 287 ++++++++++++
tests/api_resources/test_devboxes.py | 2 +
26 files changed, 1123 insertions(+), 19 deletions(-)
create mode 100644 src/runloop_api_client/resources/agents.py
create mode 100644 src/runloop_api_client/types/agent_create_params.py
create mode 100644 src/runloop_api_client/types/agent_list_params.py
create mode 100644 src/runloop_api_client/types/agent_list_view.py
create mode 100644 src/runloop_api_client/types/agent_view.py
create mode 100644 src/runloop_api_client/types/shared/agent_source.py
create mode 100644 src/runloop_api_client/types/shared_params/agent_source.py
create mode 100644 tests/api_resources/test_agents.py
diff --git a/.stats.yml b/.stats.yml
index f5090dac7..9f4451f29 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 94
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-4f5fe47eea7a16fba1ba473532c7cb9687a113cf97e7b92bac014bca728f9505.yml
-openapi_spec_hash: ae55e0436d54e239a548e245fd19a863
-config_hash: 95facb8cef59b5a1b05763b871bf6a4b
+configured_endpoints: 97
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-4a14147d9603516ef2245584e4e44af8324cb1cbf130c3718bea39ad15b8084d.yml
+openapi_spec_hash: bfeae3e75e496683934b941a19396c4b
+config_hash: 2363f563f42501d2b1587a4f64bdccaf
diff --git a/api.md b/api.md
index deb30848b..a3c529f83 100644
--- a/api.md
+++ b/api.md
@@ -4,6 +4,7 @@
from runloop_api_client.types import (
AfterIdle,
AgentMountParameters,
+ AgentSource,
CodeMountParameters,
LaunchParameters,
Mount,
@@ -47,6 +48,20 @@ Methods:
- client.benchmarks.runs.complete(id) -> BenchmarkRunView
- client.benchmarks.runs.list_scenario_runs(id, \*\*params) -> SyncBenchmarkRunsCursorIDPage[ScenarioRunView]
+# Agents
+
+Types:
+
+```python
+from runloop_api_client.types import AgentCreateParameters, AgentListView, AgentView
+```
+
+Methods:
+
+- client.agents.create(\*\*params) -> AgentView
+- client.agents.retrieve(id) -> AgentView
+- client.agents.list(\*\*params) -> SyncAgentsCursorIDPage[AgentView]
+
# Blueprints
Types:
diff --git a/src/runloop_api_client/_client.py b/src/runloop_api_client/_client.py
index bdfccf7e5..f4f6d1535 100644
--- a/src/runloop_api_client/_client.py
+++ b/src/runloop_api_client/_client.py
@@ -31,7 +31,8 @@
)
if TYPE_CHECKING:
- from .resources import objects, secrets, devboxes, scenarios, benchmarks, blueprints, repositories
+ from .resources import agents, objects, secrets, devboxes, scenarios, benchmarks, blueprints, repositories
+ from .resources.agents import AgentsResource, AsyncAgentsResource
from .resources.objects import ObjectsResource, AsyncObjectsResource
from .resources.secrets import SecretsResource, AsyncSecretsResource
from .resources.blueprints import BlueprintsResource, AsyncBlueprintsResource
@@ -106,6 +107,12 @@ def benchmarks(self) -> BenchmarksResource:
return BenchmarksResource(self)
+ @cached_property
+ def agents(self) -> AgentsResource:
+ from .resources.agents import AgentsResource
+
+ return AgentsResource(self)
+
@cached_property
def blueprints(self) -> BlueprintsResource:
from .resources.blueprints import BlueprintsResource
@@ -318,6 +325,12 @@ def benchmarks(self) -> AsyncBenchmarksResource:
return AsyncBenchmarksResource(self)
+ @cached_property
+ def agents(self) -> AsyncAgentsResource:
+ from .resources.agents import AsyncAgentsResource
+
+ return AsyncAgentsResource(self)
+
@cached_property
def blueprints(self) -> AsyncBlueprintsResource:
from .resources.blueprints import AsyncBlueprintsResource
@@ -479,6 +492,12 @@ def benchmarks(self) -> benchmarks.BenchmarksResourceWithRawResponse:
return BenchmarksResourceWithRawResponse(self._client.benchmarks)
+ @cached_property
+ def agents(self) -> agents.AgentsResourceWithRawResponse:
+ from .resources.agents import AgentsResourceWithRawResponse
+
+ return AgentsResourceWithRawResponse(self._client.agents)
+
@cached_property
def blueprints(self) -> blueprints.BlueprintsResourceWithRawResponse:
from .resources.blueprints import BlueprintsResourceWithRawResponse
@@ -528,6 +547,12 @@ def benchmarks(self) -> benchmarks.AsyncBenchmarksResourceWithRawResponse:
return AsyncBenchmarksResourceWithRawResponse(self._client.benchmarks)
+ @cached_property
+ def agents(self) -> agents.AsyncAgentsResourceWithRawResponse:
+ from .resources.agents import AsyncAgentsResourceWithRawResponse
+
+ return AsyncAgentsResourceWithRawResponse(self._client.agents)
+
@cached_property
def blueprints(self) -> blueprints.AsyncBlueprintsResourceWithRawResponse:
from .resources.blueprints import AsyncBlueprintsResourceWithRawResponse
@@ -577,6 +602,12 @@ def benchmarks(self) -> benchmarks.BenchmarksResourceWithStreamingResponse:
return BenchmarksResourceWithStreamingResponse(self._client.benchmarks)
+ @cached_property
+ def agents(self) -> agents.AgentsResourceWithStreamingResponse:
+ from .resources.agents import AgentsResourceWithStreamingResponse
+
+ return AgentsResourceWithStreamingResponse(self._client.agents)
+
@cached_property
def blueprints(self) -> blueprints.BlueprintsResourceWithStreamingResponse:
from .resources.blueprints import BlueprintsResourceWithStreamingResponse
@@ -626,6 +657,12 @@ def benchmarks(self) -> benchmarks.AsyncBenchmarksResourceWithStreamingResponse:
return AsyncBenchmarksResourceWithStreamingResponse(self._client.benchmarks)
+ @cached_property
+ def agents(self) -> agents.AsyncAgentsResourceWithStreamingResponse:
+ from .resources.agents import AsyncAgentsResourceWithStreamingResponse
+
+ return AsyncAgentsResourceWithStreamingResponse(self._client.agents)
+
@cached_property
def blueprints(self) -> blueprints.AsyncBlueprintsResourceWithStreamingResponse:
from .resources.blueprints import AsyncBlueprintsResourceWithStreamingResponse
diff --git a/src/runloop_api_client/pagination.py b/src/runloop_api_client/pagination.py
index 734b6996f..a52e69c24 100644
--- a/src/runloop_api_client/pagination.py
+++ b/src/runloop_api_client/pagination.py
@@ -16,6 +16,8 @@
"AsyncDiskSnapshotsCursorIDPage",
"SyncBenchmarksCursorIDPage",
"AsyncBenchmarksCursorIDPage",
+ "SyncAgentsCursorIDPage",
+ "AsyncAgentsCursorIDPage",
"SyncBenchmarkRunsCursorIDPage",
"AsyncBenchmarkRunsCursorIDPage",
"SyncScenariosCursorIDPage",
@@ -56,6 +58,11 @@ class BenchmarksCursorIDPageItem(Protocol):
id: str
+@runtime_checkable
+class AgentsCursorIDPageItem(Protocol):
+ id: str
+
+
@runtime_checkable
class BenchmarkRunsCursorIDPageItem(Protocol):
id: str
@@ -421,6 +428,74 @@ def next_page_info(self) -> Optional[PageInfo]:
return PageInfo(params={"starting_after": item.id})
+class SyncAgentsCursorIDPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
+ agents: List[_T]
+ has_more: Optional[bool] = None
+ total_count: Optional[int] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ agents = self.agents
+ if not agents:
+ return []
+ return agents
+
+ @override
+ def has_next_page(self) -> bool:
+ has_more = self.has_more
+ if has_more is not None and has_more is False:
+ return False
+
+ return super().has_next_page()
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ agents = self.agents
+ if not agents:
+ return None
+
+ item = cast(Any, agents[-1])
+ if not isinstance(item, AgentsCursorIDPageItem) or item.id is None: # pyright: ignore[reportUnnecessaryComparison]
+ # TODO emit warning log
+ return None
+
+ return PageInfo(params={"starting_after": item.id})
+
+
+class AsyncAgentsCursorIDPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
+ agents: List[_T]
+ has_more: Optional[bool] = None
+ total_count: Optional[int] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ agents = self.agents
+ if not agents:
+ return []
+ return agents
+
+ @override
+ def has_next_page(self) -> bool:
+ has_more = self.has_more
+ if has_more is not None and has_more is False:
+ return False
+
+ return super().has_next_page()
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ agents = self.agents
+ if not agents:
+ return None
+
+ item = cast(Any, agents[-1])
+ if not isinstance(item, AgentsCursorIDPageItem) or item.id is None: # pyright: ignore[reportUnnecessaryComparison]
+ # TODO emit warning log
+ return None
+
+ return PageInfo(params={"starting_after": item.id})
+
+
class SyncBenchmarkRunsCursorIDPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
runs: List[_T]
has_more: Optional[bool] = None
diff --git a/src/runloop_api_client/resources/__init__.py b/src/runloop_api_client/resources/__init__.py
index 72ea92468..adafc4644 100644
--- a/src/runloop_api_client/resources/__init__.py
+++ b/src/runloop_api_client/resources/__init__.py
@@ -1,5 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .agents import (
+ AgentsResource,
+ AsyncAgentsResource,
+ AgentsResourceWithRawResponse,
+ AsyncAgentsResourceWithRawResponse,
+ AgentsResourceWithStreamingResponse,
+ AsyncAgentsResourceWithStreamingResponse,
+)
from .objects import (
ObjectsResource,
AsyncObjectsResource,
@@ -64,6 +72,12 @@
"AsyncBenchmarksResourceWithRawResponse",
"BenchmarksResourceWithStreamingResponse",
"AsyncBenchmarksResourceWithStreamingResponse",
+ "AgentsResource",
+ "AsyncAgentsResource",
+ "AgentsResourceWithRawResponse",
+ "AsyncAgentsResourceWithRawResponse",
+ "AgentsResourceWithStreamingResponse",
+ "AsyncAgentsResourceWithStreamingResponse",
"BlueprintsResource",
"AsyncBlueprintsResource",
"BlueprintsResourceWithRawResponse",
diff --git a/src/runloop_api_client/resources/agents.py b/src/runloop_api_client/resources/agents.py
new file mode 100644
index 000000000..6ff202d74
--- /dev/null
+++ b/src/runloop_api_client/resources/agents.py
@@ -0,0 +1,415 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+
+import httpx
+
+from ..types import agent_list_params, agent_create_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
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..pagination import SyncAgentsCursorIDPage, AsyncAgentsCursorIDPage
+from .._base_client import AsyncPaginator, make_request_options
+from ..types.agent_view import AgentView
+from ..types.shared_params.agent_source import AgentSource
+
+__all__ = ["AgentsResource", "AsyncAgentsResource"]
+
+
+class AgentsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AgentsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#accessing-raw-response-data-eg-headers
+ """
+ return AgentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AgentsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response
+ """
+ return AgentsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ name: str,
+ source: Optional[AgentSource] | 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,
+ ) -> AgentView:
+ """Create a new Agent with a name and optional public visibility.
+
+ The Agent will be
+ assigned a unique ID.
+
+ Args:
+ name: The name of the Agent.
+
+ source: The source configuration for the Agent.
+
+ 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/agents",
+ body=maybe_transform(
+ {
+ "name": name,
+ "source": source,
+ },
+ agent_create_params.AgentCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=AgentView,
+ )
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ # 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,
+ ) -> AgentView:
+ """
+ Retrieve a specific Agent by its unique identifier.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._get(
+ f"/v1/agents/{id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentView,
+ )
+
+ def list(
+ self,
+ *,
+ is_public: bool | Omit = omit,
+ limit: int | Omit = omit,
+ name: str | Omit = omit,
+ search: str | Omit = omit,
+ starting_after: 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,
+ ) -> SyncAgentsCursorIDPage[AgentView]:
+ """
+ List all Agents for the authenticated account with pagination support.
+
+ Args:
+ is_public: Filter agents by public visibility.
+
+ limit: The limit of items to return. Default is 20.
+
+ name: Filter agents by name (partial match supported).
+
+ search: Search by agent ID or name.
+
+ starting_after: Load the next page of data starting after the item with the given ID.
+
+ 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
+ """
+ return self._get_api_list(
+ "/v1/agents",
+ page=SyncAgentsCursorIDPage[AgentView],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "is_public": is_public,
+ "limit": limit,
+ "name": name,
+ "search": search,
+ "starting_after": starting_after,
+ },
+ agent_list_params.AgentListParams,
+ ),
+ ),
+ model=AgentView,
+ )
+
+
+class AsyncAgentsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncAgentsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncAgentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAgentsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response
+ """
+ return AsyncAgentsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ name: str,
+ source: Optional[AgentSource] | 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,
+ ) -> AgentView:
+ """Create a new Agent with a name and optional public visibility.
+
+ The Agent will be
+ assigned a unique ID.
+
+ Args:
+ name: The name of the Agent.
+
+ source: The source configuration for the Agent.
+
+ 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/agents",
+ body=await async_maybe_transform(
+ {
+ "name": name,
+ "source": source,
+ },
+ agent_create_params.AgentCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=AgentView,
+ )
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ # 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,
+ ) -> AgentView:
+ """
+ Retrieve a specific Agent by its unique identifier.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._get(
+ f"/v1/agents/{id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AgentView,
+ )
+
+ def list(
+ self,
+ *,
+ is_public: bool | Omit = omit,
+ limit: int | Omit = omit,
+ name: str | Omit = omit,
+ search: str | Omit = omit,
+ starting_after: 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,
+ ) -> AsyncPaginator[AgentView, AsyncAgentsCursorIDPage[AgentView]]:
+ """
+ List all Agents for the authenticated account with pagination support.
+
+ Args:
+ is_public: Filter agents by public visibility.
+
+ limit: The limit of items to return. Default is 20.
+
+ name: Filter agents by name (partial match supported).
+
+ search: Search by agent ID or name.
+
+ starting_after: Load the next page of data starting after the item with the given ID.
+
+ 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
+ """
+ return self._get_api_list(
+ "/v1/agents",
+ page=AsyncAgentsCursorIDPage[AgentView],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "is_public": is_public,
+ "limit": limit,
+ "name": name,
+ "search": search,
+ "starting_after": starting_after,
+ },
+ agent_list_params.AgentListParams,
+ ),
+ ),
+ model=AgentView,
+ )
+
+
+class AgentsResourceWithRawResponse:
+ def __init__(self, agents: AgentsResource) -> None:
+ self._agents = agents
+
+ self.create = to_raw_response_wrapper(
+ agents.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ agents.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ agents.list,
+ )
+
+
+class AsyncAgentsResourceWithRawResponse:
+ def __init__(self, agents: AsyncAgentsResource) -> None:
+ self._agents = agents
+
+ self.create = async_to_raw_response_wrapper(
+ agents.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ agents.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ agents.list,
+ )
+
+
+class AgentsResourceWithStreamingResponse:
+ def __init__(self, agents: AgentsResource) -> None:
+ self._agents = agents
+
+ self.create = to_streamed_response_wrapper(
+ agents.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ agents.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ agents.list,
+ )
+
+
+class AsyncAgentsResourceWithStreamingResponse:
+ def __init__(self, agents: AsyncAgentsResource) -> None:
+ self._agents = agents
+
+ self.create = async_to_streamed_response_wrapper(
+ agents.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ agents.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ agents.list,
+ )
diff --git a/src/runloop_api_client/resources/blueprints.py b/src/runloop_api_client/resources/blueprints.py
index 1bbd8d4b7..fb0708314 100644
--- a/src/runloop_api_client/resources/blueprints.py
+++ b/src/runloop_api_client/resources/blueprints.py
@@ -441,8 +441,11 @@ def delete(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> object:
- """
- Delete a previously created Blueprint.
+ """Delete a previously created Blueprint.
+
+ If a blueprint has dependent snapshots,
+ it cannot be deleted. You can find them by querying: GET
+ /v1/devboxes/disk_snapshots?source_blueprint_id={blueprint_id}.
Args:
extra_headers: Send extra headers
@@ -1067,8 +1070,11 @@ async def delete(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
idempotency_key: str | None = None,
) -> object:
- """
- Delete a previously created Blueprint.
+ """Delete a previously created Blueprint.
+
+ If a blueprint has dependent snapshots,
+ it cannot be deleted. You can find them by querying: GET
+ /v1/devboxes/disk_snapshots?source_blueprint_id={blueprint_id}.
Args:
extra_headers: Send extra headers
diff --git a/src/runloop_api_client/resources/devboxes/devboxes.py b/src/runloop_api_client/resources/devboxes/devboxes.py
index 9b13767af..b8ddfb976 100644
--- a/src/runloop_api_client/resources/devboxes/devboxes.py
+++ b/src/runloop_api_client/resources/devboxes/devboxes.py
@@ -1086,6 +1086,7 @@ def list_disk_snapshots(
limit: int | Omit = omit,
metadata_key: str | Omit = omit,
metadata_key_in: str | Omit = omit,
+ source_blueprint_id: str | Omit = omit,
starting_after: 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.
@@ -1095,8 +1096,8 @@ def list_disk_snapshots(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> SyncDiskSnapshotsCursorIDPage[DevboxSnapshotView]:
"""
- List all snapshots of a Devbox while optionally filtering by Devbox ID and
- metadata.
+ List all snapshots of a Devbox while optionally filtering by Devbox ID, source
+ Blueprint ID, and metadata.
Args:
devbox_id: Devbox ID to filter by.
@@ -1108,6 +1109,8 @@ def list_disk_snapshots(
metadata_key_in: Filter snapshots by metadata key with multiple possible values (OR condition).
+ source_blueprint_id: Source Blueprint ID to filter snapshots by.
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -1132,6 +1135,7 @@ def list_disk_snapshots(
"limit": limit,
"metadata_key": metadata_key,
"metadata_key_in": metadata_key_in,
+ "source_blueprint_id": source_blueprint_id,
"starting_after": starting_after,
},
devbox_list_disk_snapshots_params.DevboxListDiskSnapshotsParams,
@@ -2618,6 +2622,7 @@ def list_disk_snapshots(
limit: int | Omit = omit,
metadata_key: str | Omit = omit,
metadata_key_in: str | Omit = omit,
+ source_blueprint_id: str | Omit = omit,
starting_after: 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.
@@ -2627,8 +2632,8 @@ def list_disk_snapshots(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AsyncPaginator[DevboxSnapshotView, AsyncDiskSnapshotsCursorIDPage[DevboxSnapshotView]]:
"""
- List all snapshots of a Devbox while optionally filtering by Devbox ID and
- metadata.
+ List all snapshots of a Devbox while optionally filtering by Devbox ID, source
+ Blueprint ID, and metadata.
Args:
devbox_id: Devbox ID to filter by.
@@ -2640,6 +2645,8 @@ def list_disk_snapshots(
metadata_key_in: Filter snapshots by metadata key with multiple possible values (OR condition).
+ source_blueprint_id: Source Blueprint ID to filter snapshots by.
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -2664,6 +2671,7 @@ def list_disk_snapshots(
"limit": limit,
"metadata_key": metadata_key,
"metadata_key_in": metadata_key_in,
+ "source_blueprint_id": source_blueprint_id,
"starting_after": starting_after,
},
devbox_list_disk_snapshots_params.DevboxListDiskSnapshotsParams,
diff --git a/src/runloop_api_client/resources/devboxes/disk_snapshots.py b/src/runloop_api_client/resources/devboxes/disk_snapshots.py
index cf6cb54e8..0e3530374 100644
--- a/src/runloop_api_client/resources/devboxes/disk_snapshots.py
+++ b/src/runloop_api_client/resources/devboxes/disk_snapshots.py
@@ -114,6 +114,7 @@ def list(
limit: int | Omit = omit,
metadata_key: str | Omit = omit,
metadata_key_in: str | Omit = omit,
+ source_blueprint_id: str | Omit = omit,
starting_after: 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.
@@ -123,8 +124,8 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> SyncDiskSnapshotsCursorIDPage[DevboxSnapshotView]:
"""
- List all snapshots of a Devbox while optionally filtering by Devbox ID and
- metadata.
+ List all snapshots of a Devbox while optionally filtering by Devbox ID, source
+ Blueprint ID, and metadata.
Args:
devbox_id: Devbox ID to filter by.
@@ -136,6 +137,8 @@ def list(
metadata_key_in: Filter snapshots by metadata key with multiple possible values (OR condition).
+ source_blueprint_id: Source Blueprint ID to filter snapshots by.
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -160,6 +163,7 @@ def list(
"limit": limit,
"metadata_key": metadata_key,
"metadata_key_in": metadata_key_in,
+ "source_blueprint_id": source_blueprint_id,
"starting_after": starting_after,
},
disk_snapshot_list_params.DiskSnapshotListParams,
@@ -361,6 +365,7 @@ def list(
limit: int | Omit = omit,
metadata_key: str | Omit = omit,
metadata_key_in: str | Omit = omit,
+ source_blueprint_id: str | Omit = omit,
starting_after: 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.
@@ -370,8 +375,8 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AsyncPaginator[DevboxSnapshotView, AsyncDiskSnapshotsCursorIDPage[DevboxSnapshotView]]:
"""
- List all snapshots of a Devbox while optionally filtering by Devbox ID and
- metadata.
+ List all snapshots of a Devbox while optionally filtering by Devbox ID, source
+ Blueprint ID, and metadata.
Args:
devbox_id: Devbox ID to filter by.
@@ -383,6 +388,8 @@ def list(
metadata_key_in: Filter snapshots by metadata key with multiple possible values (OR condition).
+ source_blueprint_id: Source Blueprint ID to filter snapshots by.
+
starting_after: Load the next page of data starting after the item with the given ID.
extra_headers: Send extra headers
@@ -407,6 +414,7 @@ def list(
"limit": limit,
"metadata_key": metadata_key,
"metadata_key_in": metadata_key_in,
+ "source_blueprint_id": source_blueprint_id,
"starting_after": starting_after,
},
disk_snapshot_list_params.DiskSnapshotListParams,
diff --git a/src/runloop_api_client/types/__init__.py b/src/runloop_api_client/types/__init__.py
index 2330d5227..4d5168b44 100644
--- a/src/runloop_api_client/types/__init__.py
+++ b/src/runloop_api_client/types/__init__.py
@@ -6,11 +6,13 @@
Mount as Mount,
AfterIdle as AfterIdle,
RunProfile as RunProfile,
+ AgentSource as AgentSource,
LaunchParameters as LaunchParameters,
CodeMountParameters as CodeMountParameters,
AgentMountParameters as AgentMountParameters,
ObjectMountParameters as ObjectMountParameters,
)
+from .agent_view import AgentView as AgentView
from .devbox_view import DevboxView as DevboxView
from .object_view import ObjectView as ObjectView
from .secret_view import SecretView as SecretView
@@ -18,17 +20,20 @@
from .scenario_view import ScenarioView as ScenarioView
from .benchmark_view import BenchmarkView as BenchmarkView
from .blueprint_view import BlueprintView as BlueprintView
+from .agent_list_view import AgentListView as AgentListView
from .devbox_list_view import DevboxListView as DevboxListView
from .object_list_view import ObjectListView as ObjectListView
from .scoring_contract import ScoringContract as ScoringContract
from .scoring_function import ScoringFunction as ScoringFunction
from .secret_list_view import SecretListView as SecretListView
+from .agent_list_params import AgentListParams as AgentListParams
from .scenario_run_view import ScenarioRunView as ScenarioRunView
from .benchmark_run_view import BenchmarkRunView as BenchmarkRunView
from .devbox_list_params import DevboxListParams as DevboxListParams
from .devbox_tunnel_view import DevboxTunnelView as DevboxTunnelView
from .object_list_params import ObjectListParams as ObjectListParams
from .secret_list_params import SecretListParams as SecretListParams
+from .agent_create_params import AgentCreateParams as AgentCreateParams
from .blueprint_build_log import BlueprintBuildLog as BlueprintBuildLog
from .blueprint_list_view import BlueprintListView as BlueprintListView
from .input_context_param import InputContextParam as InputContextParam
diff --git a/src/runloop_api_client/types/agent_create_params.py b/src/runloop_api_client/types/agent_create_params.py
new file mode 100644
index 000000000..1a3372e7e
--- /dev/null
+++ b/src/runloop_api_client/types/agent_create_params.py
@@ -0,0 +1,18 @@
+# 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
+
+from .shared_params.agent_source import AgentSource
+
+__all__ = ["AgentCreateParams"]
+
+
+class AgentCreateParams(TypedDict, total=False):
+ name: Required[str]
+ """The name of the Agent."""
+
+ source: Optional[AgentSource]
+ """The source configuration for the Agent."""
diff --git a/src/runloop_api_client/types/agent_list_params.py b/src/runloop_api_client/types/agent_list_params.py
new file mode 100644
index 000000000..a3199190b
--- /dev/null
+++ b/src/runloop_api_client/types/agent_list_params.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["AgentListParams"]
+
+
+class AgentListParams(TypedDict, total=False):
+ is_public: bool
+ """Filter agents by public visibility."""
+
+ limit: int
+ """The limit of items to return. Default is 20."""
+
+ name: str
+ """Filter agents by name (partial match supported)."""
+
+ search: str
+ """Search by agent ID or name."""
+
+ starting_after: str
+ """Load the next page of data starting after the item with the given ID."""
diff --git a/src/runloop_api_client/types/agent_list_view.py b/src/runloop_api_client/types/agent_list_view.py
new file mode 100644
index 000000000..c2a7be455
--- /dev/null
+++ b/src/runloop_api_client/types/agent_list_view.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .agent_view import AgentView
+
+__all__ = ["AgentListView"]
+
+
+class AgentListView(BaseModel):
+ agents: List[AgentView]
+ """The list of Agents."""
+
+ has_more: bool
+ """Whether there are more Agents to fetch."""
+
+ remaining_count: int
+ """The count of remaining Agents."""
+
+ total_count: int
+ """The total count of Agents."""
diff --git a/src/runloop_api_client/types/agent_view.py b/src/runloop_api_client/types/agent_view.py
new file mode 100644
index 000000000..bf2520a49
--- /dev/null
+++ b/src/runloop_api_client/types/agent_view.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+from .shared.agent_source import AgentSource
+
+__all__ = ["AgentView"]
+
+
+class AgentView(BaseModel):
+ id: str
+ """The unique identifier of the Agent."""
+
+ is_public: bool
+ """Whether the Agent is publicly accessible."""
+
+ name: str
+ """The name of the Agent."""
+
+ source: Optional[AgentSource] = None
+ """The source configuration for the Agent."""
diff --git a/src/runloop_api_client/types/devbox_list_disk_snapshots_params.py b/src/runloop_api_client/types/devbox_list_disk_snapshots_params.py
index ad476b208..7ffcf5386 100644
--- a/src/runloop_api_client/types/devbox_list_disk_snapshots_params.py
+++ b/src/runloop_api_client/types/devbox_list_disk_snapshots_params.py
@@ -25,5 +25,8 @@ class DevboxListDiskSnapshotsParams(TypedDict, total=False):
metadata_key_in: Annotated[str, PropertyInfo(alias="metadata[key][in]")]
"""Filter snapshots by metadata key with multiple possible values (OR condition)."""
+ source_blueprint_id: str
+ """Source Blueprint ID to filter snapshots by."""
+
starting_after: str
"""Load the next page of data starting after the item with the given ID."""
diff --git a/src/runloop_api_client/types/devbox_snapshot_view.py b/src/runloop_api_client/types/devbox_snapshot_view.py
index 82ae90907..477f99d4e 100644
--- a/src/runloop_api_client/types/devbox_snapshot_view.py
+++ b/src/runloop_api_client/types/devbox_snapshot_view.py
@@ -25,3 +25,6 @@ class DevboxSnapshotView(BaseModel):
name: Optional[str] = None
"""(Optional) The custom name of the snapshot."""
+
+ source_blueprint_id: Optional[str] = None
+ """(Optional) The source Blueprint ID this snapshot was created from."""
diff --git a/src/runloop_api_client/types/devboxes/disk_snapshot_list_params.py b/src/runloop_api_client/types/devboxes/disk_snapshot_list_params.py
index e43a55d1d..7b0f3454f 100644
--- a/src/runloop_api_client/types/devboxes/disk_snapshot_list_params.py
+++ b/src/runloop_api_client/types/devboxes/disk_snapshot_list_params.py
@@ -25,5 +25,8 @@ class DiskSnapshotListParams(TypedDict, total=False):
metadata_key_in: Annotated[str, PropertyInfo(alias="metadata[key][in]")]
"""Filter snapshots by metadata key with multiple possible values (OR condition)."""
+ source_blueprint_id: str
+ """Source Blueprint ID to filter snapshots by."""
+
starting_after: str
"""Load the next page of data starting after the item with the given ID."""
diff --git a/src/runloop_api_client/types/shared/__init__.py b/src/runloop_api_client/types/shared/__init__.py
index 39a3b079e..696abb529 100644
--- a/src/runloop_api_client/types/shared/__init__.py
+++ b/src/runloop_api_client/types/shared/__init__.py
@@ -3,6 +3,7 @@
from .mount import Mount as Mount
from .after_idle import AfterIdle as AfterIdle
from .run_profile import RunProfile as RunProfile
+from .agent_source import AgentSource as AgentSource
from .launch_parameters import LaunchParameters as LaunchParameters
from .code_mount_parameters import CodeMountParameters as CodeMountParameters
from .agent_mount_parameters import AgentMountParameters as AgentMountParameters
diff --git a/src/runloop_api_client/types/shared/agent_mount_parameters.py b/src/runloop_api_client/types/shared/agent_mount_parameters.py
index 5e92a0641..c2b384265 100644
--- a/src/runloop_api_client/types/shared/agent_mount_parameters.py
+++ b/src/runloop_api_client/types/shared/agent_mount_parameters.py
@@ -15,7 +15,10 @@ class AgentMountParameters(BaseModel):
type: Literal["agent_mount"]
agent_path: Optional[str] = None
- """Optional path to mount the agent on the Devbox.
+ """Path to mount the agent on the Devbox.
Required for git and object agents. Use absolute path (e.g., /home/user/agent)
"""
+
+ auth_token: Optional[str] = None
+ """Optional auth token for private repositories. Only used for git agents."""
diff --git a/src/runloop_api_client/types/shared/agent_source.py b/src/runloop_api_client/types/shared/agent_source.py
new file mode 100644
index 000000000..7dc4958d2
--- /dev/null
+++ b/src/runloop_api_client/types/shared/agent_source.py
@@ -0,0 +1,62 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+
+__all__ = ["AgentSource", "Git", "Npm", "Object", "Pip"]
+
+
+class Git(BaseModel):
+ repository: str
+ """Git repository URL"""
+
+ ref: Optional[str] = None
+ """Optional Git ref (branch/tag/commit), defaults to main/HEAD"""
+
+ setup: Optional[List[str]] = None
+ """Setup commands to run after cloning"""
+
+
+class Npm(BaseModel):
+ package_name: str
+ """NPM package name"""
+
+ npm_version: Optional[str] = None
+ """NPM version constraint"""
+
+ registry_url: Optional[str] = None
+ """NPM registry URL"""
+
+
+class Object(BaseModel):
+ object_id: str
+ """Object ID"""
+
+
+class Pip(BaseModel):
+ package_name: str
+ """Pip package name"""
+
+ pip_version: Optional[str] = None
+ """Pip version constraint"""
+
+ registry_url: Optional[str] = None
+ """Pip registry URL"""
+
+
+class AgentSource(BaseModel):
+ type: str
+ """Source type: npm, pip, object, or git"""
+
+ git: Optional[Git] = None
+ """Git source configuration"""
+
+ npm: Optional[Npm] = None
+ """NPM source configuration"""
+
+ object: Optional[Object] = None
+ """Object store source configuration"""
+
+ pip: Optional[Pip] = None
+ """Pip source configuration"""
diff --git a/src/runloop_api_client/types/shared_params/__init__.py b/src/runloop_api_client/types/shared_params/__init__.py
index 39a3b079e..696abb529 100644
--- a/src/runloop_api_client/types/shared_params/__init__.py
+++ b/src/runloop_api_client/types/shared_params/__init__.py
@@ -3,6 +3,7 @@
from .mount import Mount as Mount
from .after_idle import AfterIdle as AfterIdle
from .run_profile import RunProfile as RunProfile
+from .agent_source import AgentSource as AgentSource
from .launch_parameters import LaunchParameters as LaunchParameters
from .code_mount_parameters import CodeMountParameters as CodeMountParameters
from .agent_mount_parameters import AgentMountParameters as AgentMountParameters
diff --git a/src/runloop_api_client/types/shared_params/agent_mount_parameters.py b/src/runloop_api_client/types/shared_params/agent_mount_parameters.py
index eca7e8cf1..def126043 100644
--- a/src/runloop_api_client/types/shared_params/agent_mount_parameters.py
+++ b/src/runloop_api_client/types/shared_params/agent_mount_parameters.py
@@ -15,7 +15,10 @@ class AgentMountParameters(TypedDict, total=False):
type: Required[Literal["agent_mount"]]
agent_path: Optional[str]
- """Optional path to mount the agent on the Devbox.
+ """Path to mount the agent on the Devbox.
Required for git and object agents. Use absolute path (e.g., /home/user/agent)
"""
+
+ auth_token: Optional[str]
+ """Optional auth token for private repositories. Only used for git agents."""
diff --git a/src/runloop_api_client/types/shared_params/agent_source.py b/src/runloop_api_client/types/shared_params/agent_source.py
new file mode 100644
index 000000000..2c1ce71d3
--- /dev/null
+++ b/src/runloop_api_client/types/shared_params/agent_source.py
@@ -0,0 +1,65 @@
+# 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
+
+from ..._types import SequenceNotStr
+
+__all__ = ["AgentSource", "Git", "Npm", "Object", "Pip"]
+
+
+class Git(TypedDict, total=False):
+ repository: Required[str]
+ """Git repository URL"""
+
+ ref: Optional[str]
+ """Optional Git ref (branch/tag/commit), defaults to main/HEAD"""
+
+ setup: Optional[SequenceNotStr[str]]
+ """Setup commands to run after cloning"""
+
+
+class Npm(TypedDict, total=False):
+ package_name: Required[str]
+ """NPM package name"""
+
+ npm_version: Optional[str]
+ """NPM version constraint"""
+
+ registry_url: Optional[str]
+ """NPM registry URL"""
+
+
+class Object(TypedDict, total=False):
+ object_id: Required[str]
+ """Object ID"""
+
+
+class Pip(TypedDict, total=False):
+ package_name: Required[str]
+ """Pip package name"""
+
+ pip_version: Optional[str]
+ """Pip version constraint"""
+
+ registry_url: Optional[str]
+ """Pip registry URL"""
+
+
+class AgentSource(TypedDict, total=False):
+ type: Required[str]
+ """Source type: npm, pip, object, or git"""
+
+ git: Optional[Git]
+ """Git source configuration"""
+
+ npm: Optional[Npm]
+ """NPM source configuration"""
+
+ object: Optional[Object]
+ """Object store source configuration"""
+
+ pip: Optional[Pip]
+ """Pip source configuration"""
diff --git a/tests/api_resources/devboxes/test_disk_snapshots.py b/tests/api_resources/devboxes/test_disk_snapshots.py
index d7ae59acd..170e618ba 100644
--- a/tests/api_resources/devboxes/test_disk_snapshots.py
+++ b/tests/api_resources/devboxes/test_disk_snapshots.py
@@ -84,6 +84,7 @@ def test_method_list_with_all_params(self, client: Runloop) -> None:
limit=0,
metadata_key="metadata[key]",
metadata_key_in="metadata[key][in]",
+ source_blueprint_id="source_blueprint_id",
starting_after="starting_after",
)
assert_matches_type(SyncDiskSnapshotsCursorIDPage[DevboxSnapshotView], disk_snapshot, path=["response"])
@@ -356,6 +357,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncRunloop) ->
limit=0,
metadata_key="metadata[key]",
metadata_key_in="metadata[key][in]",
+ source_blueprint_id="source_blueprint_id",
starting_after="starting_after",
)
assert_matches_type(AsyncDiskSnapshotsCursorIDPage[DevboxSnapshotView], disk_snapshot, path=["response"])
diff --git a/tests/api_resources/test_agents.py b/tests/api_resources/test_agents.py
new file mode 100644
index 000000000..596338b85
--- /dev/null
+++ b/tests/api_resources/test_agents.py
@@ -0,0 +1,287 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from tests.utils import assert_matches_type
+from runloop_api_client import Runloop, AsyncRunloop
+from runloop_api_client.types import AgentView
+from runloop_api_client.pagination import SyncAgentsCursorIDPage, AsyncAgentsCursorIDPage
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestAgents:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Runloop) -> None:
+ agent = client.agents.create(
+ name="name",
+ )
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ def test_method_create_with_all_params(self, client: Runloop) -> None:
+ agent = client.agents.create(
+ name="name",
+ source={
+ "type": "type",
+ "git": {
+ "repository": "repository",
+ "ref": "ref",
+ "setup": ["string"],
+ },
+ "npm": {
+ "package_name": "package_name",
+ "npm_version": "npm_version",
+ "registry_url": "registry_url",
+ },
+ "object": {"object_id": "object_id"},
+ "pip": {
+ "package_name": "package_name",
+ "pip_version": "pip_version",
+ "registry_url": "registry_url",
+ },
+ },
+ )
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Runloop) -> None:
+ response = client.agents.with_raw_response.create(
+ name="name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ agent = response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Runloop) -> None:
+ with client.agents.with_streaming_response.create(
+ name="name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ agent = response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_retrieve(self, client: Runloop) -> None:
+ agent = client.agents.retrieve(
+ "id",
+ )
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ def test_raw_response_retrieve(self, client: Runloop) -> None:
+ response = client.agents.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ agent = response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Runloop) -> None:
+ with client.agents.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ agent = response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_retrieve(self, client: Runloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.agents.with_raw_response.retrieve(
+ "",
+ )
+
+ @parametrize
+ def test_method_list(self, client: Runloop) -> None:
+ agent = client.agents.list()
+ assert_matches_type(SyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Runloop) -> None:
+ agent = client.agents.list(
+ is_public=True,
+ limit=0,
+ name="name",
+ search="search",
+ starting_after="starting_after",
+ )
+ assert_matches_type(SyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Runloop) -> None:
+ response = client.agents.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ agent = response.parse()
+ assert_matches_type(SyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Runloop) -> None:
+ with client.agents.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ agent = response.parse()
+ assert_matches_type(SyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncAgents:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncRunloop) -> None:
+ agent = await async_client.agents.create(
+ name="name",
+ )
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -> None:
+ agent = await async_client.agents.create(
+ name="name",
+ source={
+ "type": "type",
+ "git": {
+ "repository": "repository",
+ "ref": "ref",
+ "setup": ["string"],
+ },
+ "npm": {
+ "package_name": "package_name",
+ "npm_version": "npm_version",
+ "registry_url": "registry_url",
+ },
+ "object": {"object_id": "object_id"},
+ "pip": {
+ "package_name": "package_name",
+ "pip_version": "pip_version",
+ "registry_url": "registry_url",
+ },
+ },
+ )
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.agents.with_raw_response.create(
+ name="name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ agent = await response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncRunloop) -> None:
+ async with async_client.agents.with_streaming_response.create(
+ name="name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ agent = await response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncRunloop) -> None:
+ agent = await async_client.agents.retrieve(
+ "id",
+ )
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.agents.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ agent = await response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncRunloop) -> None:
+ async with async_client.agents.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ agent = await response.parse()
+ assert_matches_type(AgentView, agent, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncRunloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.agents.with_raw_response.retrieve(
+ "",
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncRunloop) -> None:
+ agent = await async_client.agents.list()
+ assert_matches_type(AsyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> None:
+ agent = await async_client.agents.list(
+ is_public=True,
+ limit=0,
+ name="name",
+ search="search",
+ starting_after="starting_after",
+ )
+ assert_matches_type(AsyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.agents.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ agent = await response.parse()
+ assert_matches_type(AsyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncRunloop) -> None:
+ async with async_client.agents.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ agent = await response.parse()
+ assert_matches_type(AsyncAgentsCursorIDPage[AgentView], agent, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_devboxes.py b/tests/api_resources/test_devboxes.py
index 98d0a4a7a..ede4c70cf 100644
--- a/tests/api_resources/test_devboxes.py
+++ b/tests/api_resources/test_devboxes.py
@@ -633,6 +633,7 @@ def test_method_list_disk_snapshots_with_all_params(self, client: Runloop) -> No
limit=0,
metadata_key="metadata[key]",
metadata_key_in="metadata[key][in]",
+ source_blueprint_id="source_blueprint_id",
starting_after="starting_after",
)
assert_matches_type(SyncDiskSnapshotsCursorIDPage[DevboxSnapshotView], devbox, path=["response"])
@@ -2180,6 +2181,7 @@ async def test_method_list_disk_snapshots_with_all_params(self, async_client: As
limit=0,
metadata_key="metadata[key]",
metadata_key_in="metadata[key][in]",
+ source_blueprint_id="source_blueprint_id",
starting_after="starting_after",
)
assert_matches_type(AsyncDiskSnapshotsCursorIDPage[DevboxSnapshotView], devbox, path=["response"])
From 7c265936088c074d00bd3c65b52dde5dcde3ccfb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 14 Nov 2025 02:18:20 +0000
Subject: [PATCH 07/11] fix(snapshot): added "deleted" status to
DevboxSnapshotStatus enum \n fix(storage-object): added ObjectState enum,
fixed createObject() to appropriately type content_type and state as the
respective enums
---
.stats.yml | 4 +-
src/runloop_api_client/resources/objects.py | 50 +++++++++++--------
.../devbox_snapshot_async_status_view.py | 2 +-
.../types/object_create_params.py | 6 +++
.../types/object_list_params.py | 12 ++---
.../types/object_list_public_params.py | 12 ++---
src/runloop_api_client/types/object_view.py | 5 +-
tests/api_resources/test_objects.py | 18 ++++---
8 files changed, 65 insertions(+), 44 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 9f4451f29..a331aec18 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 97
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-4a14147d9603516ef2245584e4e44af8324cb1cbf130c3718bea39ad15b8084d.yml
-openapi_spec_hash: bfeae3e75e496683934b941a19396c4b
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-9f8a6310d4d9c36d386f5afe17cfc891d05d5911204574645f9f90d9b6864a00.yml
+openapi_spec_hash: 3fc0a807bb8d728abe3b7eaff0b9f7ec
config_hash: 2363f563f42501d2b1587a4f64bdccaf
diff --git a/src/runloop_api_client/resources/objects.py b/src/runloop_api_client/resources/objects.py
index 3f83830e6..4d7d2e0a3 100644
--- a/src/runloop_api_client/resources/objects.py
+++ b/src/runloop_api_client/resources/objects.py
@@ -52,6 +52,7 @@ def create(
content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"],
name: str,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ ttl_ms: Optional[int] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -72,6 +73,9 @@ def create(
metadata: User defined metadata to attach to the object for organization.
+ ttl_ms: Optional lifetime of the object in milliseconds, after which the object is
+ automatically deleted. Time starts ticking after the object is created.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -89,6 +93,7 @@ def create(
"content_type": content_type,
"name": name,
"metadata": metadata,
+ "ttl_ms": ttl_ms,
},
object_create_params.ObjectCreateParams,
),
@@ -138,12 +143,12 @@ def retrieve(
def list(
self,
*,
- content_type: str | Omit = omit,
+ content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"] | Omit = omit,
limit: int | Omit = omit,
name: str | Omit = omit,
search: str | Omit = omit,
starting_after: str | Omit = omit,
- state: str | Omit = omit,
+ state: Literal["UPLOADING", "READ_ONLY", "DELETED", "ERROR"] | 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,
@@ -155,17 +160,17 @@ def list(
List all Objects for the authenticated account with pagination support.
Args:
- content_type: Filter objects by content type.
+ content_type: Filter storage objects by content type.
limit: The limit of items to return. Default is 20.
- name: Filter objects by name (partial match supported).
+ name: Filter storage objects by name (partial match supported).
search: Search by object ID or name.
starting_after: Load the next page of data starting after the item with the given ID.
- state: Filter objects by state (UPLOADING, READ_ONLY, DELETED).
+ state: Filter storage objects by state.
extra_headers: Send extra headers
@@ -328,12 +333,12 @@ def download(
def list_public(
self,
*,
- content_type: str | Omit = omit,
+ content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"] | Omit = omit,
limit: int | Omit = omit,
name: str | Omit = omit,
search: str | Omit = omit,
starting_after: str | Omit = omit,
- state: str | Omit = omit,
+ state: Literal["UPLOADING", "READ_ONLY", "DELETED", "ERROR"] | 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,
@@ -345,17 +350,17 @@ def list_public(
List all public Objects with pagination support.
Args:
- content_type: Filter objects by content type.
+ content_type: Filter storage objects by content type.
limit: The limit of items to return. Default is 20.
- name: Filter objects by name (partial match supported).
+ name: Filter storage objects by name (partial match supported).
search: Search by object ID or name.
starting_after: Load the next page of data starting after the item with the given ID.
- state: Filter objects by state (UPLOADING, READ_ONLY, DELETED).
+ state: Filter storage objects by state.
extra_headers: Send extra headers
@@ -415,6 +420,7 @@ async def create(
content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"],
name: str,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ ttl_ms: Optional[int] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -435,6 +441,9 @@ async def create(
metadata: User defined metadata to attach to the object for organization.
+ ttl_ms: Optional lifetime of the object in milliseconds, after which the object is
+ automatically deleted. Time starts ticking after the object is created.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -452,6 +461,7 @@ async def create(
"content_type": content_type,
"name": name,
"metadata": metadata,
+ "ttl_ms": ttl_ms,
},
object_create_params.ObjectCreateParams,
),
@@ -501,12 +511,12 @@ async def retrieve(
def list(
self,
*,
- content_type: str | Omit = omit,
+ content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"] | Omit = omit,
limit: int | Omit = omit,
name: str | Omit = omit,
search: str | Omit = omit,
starting_after: str | Omit = omit,
- state: str | Omit = omit,
+ state: Literal["UPLOADING", "READ_ONLY", "DELETED", "ERROR"] | 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,
@@ -518,17 +528,17 @@ def list(
List all Objects for the authenticated account with pagination support.
Args:
- content_type: Filter objects by content type.
+ content_type: Filter storage objects by content type.
limit: The limit of items to return. Default is 20.
- name: Filter objects by name (partial match supported).
+ name: Filter storage objects by name (partial match supported).
search: Search by object ID or name.
starting_after: Load the next page of data starting after the item with the given ID.
- state: Filter objects by state (UPLOADING, READ_ONLY, DELETED).
+ state: Filter storage objects by state.
extra_headers: Send extra headers
@@ -691,12 +701,12 @@ async def download(
def list_public(
self,
*,
- content_type: str | Omit = omit,
+ content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"] | Omit = omit,
limit: int | Omit = omit,
name: str | Omit = omit,
search: str | Omit = omit,
starting_after: str | Omit = omit,
- state: str | Omit = omit,
+ state: Literal["UPLOADING", "READ_ONLY", "DELETED", "ERROR"] | 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,
@@ -708,17 +718,17 @@ def list_public(
List all public Objects with pagination support.
Args:
- content_type: Filter objects by content type.
+ content_type: Filter storage objects by content type.
limit: The limit of items to return. Default is 20.
- name: Filter objects by name (partial match supported).
+ name: Filter storage objects by name (partial match supported).
search: Search by object ID or name.
starting_after: Load the next page of data starting after the item with the given ID.
- state: Filter objects by state (UPLOADING, READ_ONLY, DELETED).
+ state: Filter storage objects by state.
extra_headers: Send extra headers
diff --git a/src/runloop_api_client/types/devboxes/devbox_snapshot_async_status_view.py b/src/runloop_api_client/types/devboxes/devbox_snapshot_async_status_view.py
index 2c7ea8eee..11abaa62f 100644
--- a/src/runloop_api_client/types/devboxes/devbox_snapshot_async_status_view.py
+++ b/src/runloop_api_client/types/devboxes/devbox_snapshot_async_status_view.py
@@ -10,7 +10,7 @@
class DevboxSnapshotAsyncStatusView(BaseModel):
- status: Literal["in_progress", "error", "complete"]
+ status: Literal["in_progress", "error", "complete", "deleted"]
"""The current status of the snapshot operation."""
error_message: Optional[str] = None
diff --git a/src/runloop_api_client/types/object_create_params.py b/src/runloop_api_client/types/object_create_params.py
index 99cdff0e7..c48a767f0 100644
--- a/src/runloop_api_client/types/object_create_params.py
+++ b/src/runloop_api_client/types/object_create_params.py
@@ -22,3 +22,9 @@ class ObjectCreateParams(TypedDict, total=False):
metadata: Optional[Dict[str, str]]
"""User defined metadata to attach to the object for organization."""
+
+ ttl_ms: Optional[int]
+ """
+ Optional lifetime of the object in milliseconds, after which the object is
+ automatically deleted. Time starts ticking after the object is created.
+ """
diff --git a/src/runloop_api_client/types/object_list_params.py b/src/runloop_api_client/types/object_list_params.py
index 044cff81a..084fac54d 100644
--- a/src/runloop_api_client/types/object_list_params.py
+++ b/src/runloop_api_client/types/object_list_params.py
@@ -2,20 +2,20 @@
from __future__ import annotations
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["ObjectListParams"]
class ObjectListParams(TypedDict, total=False):
- content_type: str
- """Filter objects by content type."""
+ content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"]
+ """Filter storage objects by content type."""
limit: int
"""The limit of items to return. Default is 20."""
name: str
- """Filter objects by name (partial match supported)."""
+ """Filter storage objects by name (partial match supported)."""
search: str
"""Search by object ID or name."""
@@ -23,5 +23,5 @@ class ObjectListParams(TypedDict, total=False):
starting_after: str
"""Load the next page of data starting after the item with the given ID."""
- state: str
- """Filter objects by state (UPLOADING, READ_ONLY, DELETED)."""
+ state: Literal["UPLOADING", "READ_ONLY", "DELETED", "ERROR"]
+ """Filter storage objects by state."""
diff --git a/src/runloop_api_client/types/object_list_public_params.py b/src/runloop_api_client/types/object_list_public_params.py
index a69ef53dd..19b18ba49 100644
--- a/src/runloop_api_client/types/object_list_public_params.py
+++ b/src/runloop_api_client/types/object_list_public_params.py
@@ -2,20 +2,20 @@
from __future__ import annotations
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["ObjectListPublicParams"]
class ObjectListPublicParams(TypedDict, total=False):
- content_type: str
- """Filter objects by content type."""
+ content_type: Literal["unspecified", "text", "binary", "gzip", "tar", "tgz"]
+ """Filter storage objects by content type."""
limit: int
"""The limit of items to return. Default is 20."""
name: str
- """Filter objects by name (partial match supported)."""
+ """Filter storage objects by name (partial match supported)."""
search: str
"""Search by object ID or name."""
@@ -23,5 +23,5 @@ class ObjectListPublicParams(TypedDict, total=False):
starting_after: str
"""Load the next page of data starting after the item with the given ID."""
- state: str
- """Filter objects by state (UPLOADING, READ_ONLY, DELETED)."""
+ state: Literal["UPLOADING", "READ_ONLY", "DELETED", "ERROR"]
+ """Filter storage objects by state."""
diff --git a/src/runloop_api_client/types/object_view.py b/src/runloop_api_client/types/object_view.py
index b8a2e0f4c..80aea62ed 100644
--- a/src/runloop_api_client/types/object_view.py
+++ b/src/runloop_api_client/types/object_view.py
@@ -21,9 +21,12 @@ class ObjectView(BaseModel):
name: str
"""The name of the Object."""
- state: str
+ state: Literal["UPLOADING", "READ_ONLY", "DELETED", "ERROR"]
"""The current state of the Object."""
+ delete_after_time_ms: Optional[int] = None
+ """The time after which the Object will be deleted in milliseconds since epoch."""
+
size_bytes: Optional[int] = None
"""The size of the Object content in bytes (null until uploaded)."""
diff --git a/tests/api_resources/test_objects.py b/tests/api_resources/test_objects.py
index cf5a4cd3b..2593e03bf 100644
--- a/tests/api_resources/test_objects.py
+++ b/tests/api_resources/test_objects.py
@@ -35,6 +35,7 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
content_type="unspecified",
name="name",
metadata={"foo": "string"},
+ ttl_ms=0,
)
assert_matches_type(ObjectView, object_, path=["response"])
@@ -110,12 +111,12 @@ def test_method_list(self, client: Runloop) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Runloop) -> None:
object_ = client.objects.list(
- content_type="content_type",
+ content_type="unspecified",
limit=0,
name="name",
search="search",
starting_after="starting_after",
- state="state",
+ state="UPLOADING",
)
assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"])
@@ -269,12 +270,12 @@ def test_method_list_public(self, client: Runloop) -> None:
@parametrize
def test_method_list_public_with_all_params(self, client: Runloop) -> None:
object_ = client.objects.list_public(
- content_type="content_type",
+ content_type="unspecified",
limit=0,
name="name",
search="search",
starting_after="starting_after",
- state="state",
+ state="UPLOADING",
)
assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"])
@@ -318,6 +319,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
content_type="unspecified",
name="name",
metadata={"foo": "string"},
+ ttl_ms=0,
)
assert_matches_type(ObjectView, object_, path=["response"])
@@ -393,12 +395,12 @@ async def test_method_list(self, async_client: AsyncRunloop) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> None:
object_ = await async_client.objects.list(
- content_type="content_type",
+ content_type="unspecified",
limit=0,
name="name",
search="search",
starting_after="starting_after",
- state="state",
+ state="UPLOADING",
)
assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"])
@@ -552,12 +554,12 @@ async def test_method_list_public(self, async_client: AsyncRunloop) -> None:
@parametrize
async def test_method_list_public_with_all_params(self, async_client: AsyncRunloop) -> None:
object_ = await async_client.objects.list_public(
- content_type="content_type",
+ content_type="unspecified",
limit=0,
name="name",
search="search",
starting_after="starting_after",
- state="state",
+ state="UPLOADING",
)
assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"])
From f2bc83c126696aea224bb5978294fc3362a94eeb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 18 Nov 2025 01:39:36 +0000
Subject: [PATCH 08/11] feat(object): Added ability to give objects a Time To
Live, after which they are automatically deleted.\nfeat(blueprints): Added
the ability to attach objects as build contexts that can be referenced in
your Dockerfile.
---
.stats.yml | 4 +-
.../resources/blueprints.py | 44 ++++++++++++
.../types/blueprint_build_parameters.py | 66 +++++++++++++++++-
.../types/blueprint_create_params.py | 67 ++++++++++++++++++-
.../types/blueprint_preview_params.py | 67 ++++++++++++++++++-
src/runloop_api_client/types/devbox_view.py | 3 +-
.../types/shared/agent_source.py | 15 ++++-
.../types/shared_params/agent_source.py | 15 ++++-
tests/api_resources/test_agents.py | 18 +++--
tests/api_resources/test_blueprints.py | 48 +++++++++++++
10 files changed, 329 insertions(+), 18 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index a331aec18..2ee72efab 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 97
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-9f8a6310d4d9c36d386f5afe17cfc891d05d5911204574645f9f90d9b6864a00.yml
-openapi_spec_hash: 3fc0a807bb8d728abe3b7eaff0b9f7ec
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-779f7a8b0be0c3d2d095c6256d35c5dbb4c28d049f3541384c51a8c215e8a87a.yml
+openapi_spec_hash: b4ebc80eeaf4e5b3bcd53c30433cf35e
config_hash: 2363f563f42501d2b1587a4f64bdccaf
diff --git a/src/runloop_api_client/resources/blueprints.py b/src/runloop_api_client/resources/blueprints.py
index fb0708314..8f2672da8 100644
--- a/src/runloop_api_client/resources/blueprints.py
+++ b/src/runloop_api_client/resources/blueprints.py
@@ -131,10 +131,12 @@ def create(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
+ build_contexts: Optional[Dict[str, blueprint_create_params.BuildContexts]] | 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,
+ local_build_context: Optional[blueprint_create_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
@@ -167,6 +169,11 @@ def create(
build_args: (Optional) Arbitrary Docker build args to pass during build.
+ build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
+ are typed context definitions (object or http). See Docker buildx additional
+ contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
code_mounts: A list of code mounts to be included in the Blueprint.
dockerfile: Dockerfile contents to be used to build the Blueprint.
@@ -175,6 +182,8 @@ def create(
launch_parameters: Parameters to configure your Devbox at launch time.
+ local_build_context: (Optional) Local build context stored in object-storage.
+
metadata: (Optional) User defined metadata for the Blueprint.
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
@@ -210,10 +219,12 @@ def create(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
+ "build_contexts": build_contexts,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
+ "local_build_context": local_build_context,
"metadata": metadata,
"secrets": secrets,
"services": services,
@@ -638,10 +649,12 @@ def preview(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
+ build_contexts: Optional[Dict[str, blueprint_preview_params.BuildContexts]] | 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,
+ local_build_context: Optional[blueprint_preview_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_preview_params.Service]] | Omit = omit,
@@ -672,6 +685,11 @@ def preview(
build_args: (Optional) Arbitrary Docker build args to pass during build.
+ build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
+ are typed context definitions (object or http). See Docker buildx additional
+ contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
code_mounts: A list of code mounts to be included in the Blueprint.
dockerfile: Dockerfile contents to be used to build the Blueprint.
@@ -680,6 +698,8 @@ def preview(
launch_parameters: Parameters to configure your Devbox at launch time.
+ local_build_context: (Optional) Local build context stored in object-storage.
+
metadata: (Optional) User defined metadata for the Blueprint.
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
@@ -711,10 +731,12 @@ def preview(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
+ "build_contexts": build_contexts,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
+ "local_build_context": local_build_context,
"metadata": metadata,
"secrets": secrets,
"services": services,
@@ -760,10 +782,12 @@ async def create(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
+ build_contexts: Optional[Dict[str, blueprint_create_params.BuildContexts]] | 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,
+ local_build_context: Optional[blueprint_create_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
@@ -796,6 +820,11 @@ async def create(
build_args: (Optional) Arbitrary Docker build args to pass during build.
+ build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
+ are typed context definitions (object or http). See Docker buildx additional
+ contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
code_mounts: A list of code mounts to be included in the Blueprint.
dockerfile: Dockerfile contents to be used to build the Blueprint.
@@ -804,6 +833,8 @@ async def create(
launch_parameters: Parameters to configure your Devbox at launch time.
+ local_build_context: (Optional) Local build context stored in object-storage.
+
metadata: (Optional) User defined metadata for the Blueprint.
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
@@ -839,10 +870,12 @@ async def create(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
+ "build_contexts": build_contexts,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
+ "local_build_context": local_build_context,
"metadata": metadata,
"secrets": secrets,
"services": services,
@@ -1267,10 +1300,12 @@ async def preview(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
+ build_contexts: Optional[Dict[str, blueprint_preview_params.BuildContexts]] | 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,
+ local_build_context: Optional[blueprint_preview_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_preview_params.Service]] | Omit = omit,
@@ -1301,6 +1336,11 @@ async def preview(
build_args: (Optional) Arbitrary Docker build args to pass during build.
+ build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
+ are typed context definitions (object or http). See Docker buildx additional
+ contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
code_mounts: A list of code mounts to be included in the Blueprint.
dockerfile: Dockerfile contents to be used to build the Blueprint.
@@ -1309,6 +1349,8 @@ async def preview(
launch_parameters: Parameters to configure your Devbox at launch time.
+ local_build_context: (Optional) Local build context stored in object-storage.
+
metadata: (Optional) User defined metadata for the Blueprint.
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
@@ -1340,10 +1382,12 @@ async def preview(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
+ "build_contexts": build_contexts,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
+ "local_build_context": local_build_context,
"metadata": metadata,
"secrets": secrets,
"services": services,
diff --git a/src/runloop_api_client/types/blueprint_build_parameters.py b/src/runloop_api_client/types/blueprint_build_parameters.py
index 63a92f146..25bac19d7 100644
--- a/src/runloop_api_client/types/blueprint_build_parameters.py
+++ b/src/runloop_api_client/types/blueprint_build_parameters.py
@@ -1,12 +1,65 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Dict, List, Optional
+from typing_extensions import Literal
from .._models import BaseModel
from .shared.launch_parameters import LaunchParameters
from .shared.code_mount_parameters import CodeMountParameters
-__all__ = ["BlueprintBuildParameters", "Service", "ServiceCredentials"]
+__all__ = [
+ "BlueprintBuildParameters",
+ "BuildContexts",
+ "BuildContextsHTTP",
+ "BuildContextsObject",
+ "LocalBuildContext",
+ "LocalBuildContextHTTP",
+ "LocalBuildContextObject",
+ "Service",
+ "ServiceCredentials",
+]
+
+
+class BuildContextsHTTP(BaseModel):
+ url: str
+ """HTTP(S) URL to a tarball or directory to use as context."""
+
+
+class BuildContextsObject(BaseModel):
+ object_id: str
+ """Handle for a Runloop stored object to use as context."""
+
+
+class BuildContexts(BaseModel):
+ type: Literal["OBJECT", "HTTP"]
+ """Type of the context. Supported values: object, http"""
+
+ http: Optional[BuildContextsHTTP] = None
+ """HTTP(S) context parameters."""
+
+ object: Optional[BuildContextsObject] = None
+ """Object context parameters (named build context)."""
+
+
+class LocalBuildContextHTTP(BaseModel):
+ url: str
+ """HTTP(S) URL to a tarball or directory to use as context."""
+
+
+class LocalBuildContextObject(BaseModel):
+ object_id: str
+ """Handle for a Runloop stored object to use as context."""
+
+
+class LocalBuildContext(BaseModel):
+ type: Literal["OBJECT", "HTTP"]
+ """Type of the context. Supported values: object, http"""
+
+ http: Optional[LocalBuildContextHTTP] = None
+ """HTTP(S) context parameters."""
+
+ object: Optional[LocalBuildContextObject] = None
+ """Object context parameters (named build context)."""
class ServiceCredentials(BaseModel):
@@ -61,6 +114,14 @@ class BlueprintBuildParameters(BaseModel):
build_args: Optional[Dict[str, str]] = None
"""(Optional) Arbitrary Docker build args to pass during build."""
+ build_contexts: Optional[Dict[str, BuildContexts]] = None
+ """(Optional) Map of named Docker build contexts.
+
+ Keys are context names, values are typed context definitions (object or http).
+ See Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ """
+
code_mounts: Optional[List[CodeMountParameters]] = None
"""A list of code mounts to be included in the Blueprint."""
@@ -73,6 +134,9 @@ class BlueprintBuildParameters(BaseModel):
launch_parameters: Optional[LaunchParameters] = None
"""Parameters to configure your Devbox at launch time."""
+ local_build_context: Optional[LocalBuildContext] = None
+ """(Optional) Local build context stored in object-storage."""
+
metadata: Optional[Dict[str, str]] = None
"""(Optional) User defined metadata for 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 9d0a15848..d2d94a3a8 100644
--- a/src/runloop_api_client/types/blueprint_create_params.py
+++ b/src/runloop_api_client/types/blueprint_create_params.py
@@ -3,13 +3,23 @@
from __future__ import annotations
from typing import Dict, Iterable, Optional
-from typing_extensions import Required, TypedDict
+from typing_extensions import Literal, Required, TypedDict
from .._types import SequenceNotStr
from .shared_params.launch_parameters import LaunchParameters
from .shared_params.code_mount_parameters import CodeMountParameters
-__all__ = ["BlueprintCreateParams", "Service", "ServiceCredentials"]
+__all__ = [
+ "BlueprintCreateParams",
+ "BuildContexts",
+ "BuildContextsHTTP",
+ "BuildContextsObject",
+ "LocalBuildContext",
+ "LocalBuildContextHTTP",
+ "LocalBuildContextObject",
+ "Service",
+ "ServiceCredentials",
+]
class BlueprintCreateParams(TypedDict, total=False):
@@ -33,6 +43,14 @@ class BlueprintCreateParams(TypedDict, total=False):
build_args: Optional[Dict[str, str]]
"""(Optional) Arbitrary Docker build args to pass during build."""
+ build_contexts: Optional[Dict[str, BuildContexts]]
+ """(Optional) Map of named Docker build contexts.
+
+ Keys are context names, values are typed context definitions (object or http).
+ See Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ """
+
code_mounts: Optional[Iterable[CodeMountParameters]]
"""A list of code mounts to be included in the Blueprint."""
@@ -45,6 +63,9 @@ class BlueprintCreateParams(TypedDict, total=False):
launch_parameters: Optional[LaunchParameters]
"""Parameters to configure your Devbox at launch time."""
+ local_build_context: Optional[LocalBuildContext]
+ """(Optional) Local build context stored in object-storage."""
+
metadata: Optional[Dict[str, str]]
"""(Optional) User defined metadata for the Blueprint."""
@@ -67,6 +88,48 @@ class BlueprintCreateParams(TypedDict, total=False):
"""A list of commands to run to set up your system."""
+class BuildContextsHTTP(TypedDict, total=False):
+ url: Required[str]
+ """HTTP(S) URL to a tarball or directory to use as context."""
+
+
+class BuildContextsObject(TypedDict, total=False):
+ object_id: Required[str]
+ """Handle for a Runloop stored object to use as context."""
+
+
+class BuildContexts(TypedDict, total=False):
+ type: Required[Literal["OBJECT", "HTTP"]]
+ """Type of the context. Supported values: object, http"""
+
+ http: Optional[BuildContextsHTTP]
+ """HTTP(S) context parameters."""
+
+ object: Optional[BuildContextsObject]
+ """Object context parameters (named build context)."""
+
+
+class LocalBuildContextHTTP(TypedDict, total=False):
+ url: Required[str]
+ """HTTP(S) URL to a tarball or directory to use as context."""
+
+
+class LocalBuildContextObject(TypedDict, total=False):
+ object_id: Required[str]
+ """Handle for a Runloop stored object to use as context."""
+
+
+class LocalBuildContext(TypedDict, total=False):
+ type: Required[Literal["OBJECT", "HTTP"]]
+ """Type of the context. Supported values: object, http"""
+
+ http: Optional[LocalBuildContextHTTP]
+ """HTTP(S) context parameters."""
+
+ object: Optional[LocalBuildContextObject]
+ """Object context parameters (named build context)."""
+
+
class ServiceCredentials(TypedDict, total=False):
password: Required[str]
"""The password of the container service."""
diff --git a/src/runloop_api_client/types/blueprint_preview_params.py b/src/runloop_api_client/types/blueprint_preview_params.py
index 5c1e257f2..c58487655 100644
--- a/src/runloop_api_client/types/blueprint_preview_params.py
+++ b/src/runloop_api_client/types/blueprint_preview_params.py
@@ -3,13 +3,23 @@
from __future__ import annotations
from typing import Dict, Iterable, Optional
-from typing_extensions import Required, TypedDict
+from typing_extensions import Literal, Required, TypedDict
from .._types import SequenceNotStr
from .shared_params.launch_parameters import LaunchParameters
from .shared_params.code_mount_parameters import CodeMountParameters
-__all__ = ["BlueprintPreviewParams", "Service", "ServiceCredentials"]
+__all__ = [
+ "BlueprintPreviewParams",
+ "BuildContexts",
+ "BuildContextsHTTP",
+ "BuildContextsObject",
+ "LocalBuildContext",
+ "LocalBuildContextHTTP",
+ "LocalBuildContextObject",
+ "Service",
+ "ServiceCredentials",
+]
class BlueprintPreviewParams(TypedDict, total=False):
@@ -33,6 +43,14 @@ class BlueprintPreviewParams(TypedDict, total=False):
build_args: Optional[Dict[str, str]]
"""(Optional) Arbitrary Docker build args to pass during build."""
+ build_contexts: Optional[Dict[str, BuildContexts]]
+ """(Optional) Map of named Docker build contexts.
+
+ Keys are context names, values are typed context definitions (object or http).
+ See Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ """
+
code_mounts: Optional[Iterable[CodeMountParameters]]
"""A list of code mounts to be included in the Blueprint."""
@@ -45,6 +63,9 @@ class BlueprintPreviewParams(TypedDict, total=False):
launch_parameters: Optional[LaunchParameters]
"""Parameters to configure your Devbox at launch time."""
+ local_build_context: Optional[LocalBuildContext]
+ """(Optional) Local build context stored in object-storage."""
+
metadata: Optional[Dict[str, str]]
"""(Optional) User defined metadata for the Blueprint."""
@@ -67,6 +88,48 @@ class BlueprintPreviewParams(TypedDict, total=False):
"""A list of commands to run to set up your system."""
+class BuildContextsHTTP(TypedDict, total=False):
+ url: Required[str]
+ """HTTP(S) URL to a tarball or directory to use as context."""
+
+
+class BuildContextsObject(TypedDict, total=False):
+ object_id: Required[str]
+ """Handle for a Runloop stored object to use as context."""
+
+
+class BuildContexts(TypedDict, total=False):
+ type: Required[Literal["OBJECT", "HTTP"]]
+ """Type of the context. Supported values: object, http"""
+
+ http: Optional[BuildContextsHTTP]
+ """HTTP(S) context parameters."""
+
+ object: Optional[BuildContextsObject]
+ """Object context parameters (named build context)."""
+
+
+class LocalBuildContextHTTP(TypedDict, total=False):
+ url: Required[str]
+ """HTTP(S) URL to a tarball or directory to use as context."""
+
+
+class LocalBuildContextObject(TypedDict, total=False):
+ object_id: Required[str]
+ """Handle for a Runloop stored object to use as context."""
+
+
+class LocalBuildContext(TypedDict, total=False):
+ type: Required[Literal["OBJECT", "HTTP"]]
+ """Type of the context. Supported values: object, http"""
+
+ http: Optional[LocalBuildContextHTTP]
+ """HTTP(S) context parameters."""
+
+ object: Optional[LocalBuildContextObject]
+ """Object context parameters (named build context)."""
+
+
class ServiceCredentials(TypedDict, total=False):
password: Required[str]
"""The password of the container service."""
diff --git a/src/runloop_api_client/types/devbox_view.py b/src/runloop_api_client/types/devbox_view.py
index 68240f25d..007af6575 100644
--- a/src/runloop_api_client/types/devbox_view.py
+++ b/src/runloop_api_client/types/devbox_view.py
@@ -18,7 +18,7 @@ class StateTransition(BaseModel):
provisioning: Runloop is allocating and booting the necessary infrastructure
resources. initializing: Runloop defined boot scripts are running to enable the
environment for interaction. running: The Devbox is ready for interaction.
- suspending: The Devbox disk is being snaphsotted and as part of suspension.
+ suspending: The Devbox disk is being snapshotted as part of suspension.
suspended: The Devbox disk is saved and no more active compute is being used for
the Devbox. resuming: The Devbox disk is being loaded as part of booting a
suspended Devbox. failure: The Devbox failed as part of booting or running user
@@ -27,6 +27,7 @@ class StateTransition(BaseModel):
"""
transition_time_ms: Optional[object] = None
+ """The time the status change occurred"""
class DevboxView(BaseModel):
diff --git a/src/runloop_api_client/types/shared/agent_source.py b/src/runloop_api_client/types/shared/agent_source.py
index 7dc4958d2..25bcbbc1d 100644
--- a/src/runloop_api_client/types/shared/agent_source.py
+++ b/src/runloop_api_client/types/shared/agent_source.py
@@ -11,17 +11,20 @@ class Git(BaseModel):
repository: str
"""Git repository URL"""
+ agent_setup: Optional[List[str]] = None
+ """Setup commands to run after cloning"""
+
ref: Optional[str] = None
"""Optional Git ref (branch/tag/commit), defaults to main/HEAD"""
- setup: Optional[List[str]] = None
- """Setup commands to run after cloning"""
-
class Npm(BaseModel):
package_name: str
"""NPM package name"""
+ agent_setup: Optional[List[str]] = None
+ """Setup commands to run after installation"""
+
npm_version: Optional[str] = None
"""NPM version constraint"""
@@ -33,11 +36,17 @@ class Object(BaseModel):
object_id: str
"""Object ID"""
+ agent_setup: Optional[List[str]] = None
+ """Setup commands to run after unpacking"""
+
class Pip(BaseModel):
package_name: str
"""Pip package name"""
+ agent_setup: Optional[List[str]] = None
+ """Setup commands to run after installation"""
+
pip_version: Optional[str] = None
"""Pip version constraint"""
diff --git a/src/runloop_api_client/types/shared_params/agent_source.py b/src/runloop_api_client/types/shared_params/agent_source.py
index 2c1ce71d3..9f5a50845 100644
--- a/src/runloop_api_client/types/shared_params/agent_source.py
+++ b/src/runloop_api_client/types/shared_params/agent_source.py
@@ -14,17 +14,20 @@ class Git(TypedDict, total=False):
repository: Required[str]
"""Git repository URL"""
+ agent_setup: Optional[SequenceNotStr[str]]
+ """Setup commands to run after cloning"""
+
ref: Optional[str]
"""Optional Git ref (branch/tag/commit), defaults to main/HEAD"""
- setup: Optional[SequenceNotStr[str]]
- """Setup commands to run after cloning"""
-
class Npm(TypedDict, total=False):
package_name: Required[str]
"""NPM package name"""
+ agent_setup: Optional[SequenceNotStr[str]]
+ """Setup commands to run after installation"""
+
npm_version: Optional[str]
"""NPM version constraint"""
@@ -36,11 +39,17 @@ class Object(TypedDict, total=False):
object_id: Required[str]
"""Object ID"""
+ agent_setup: Optional[SequenceNotStr[str]]
+ """Setup commands to run after unpacking"""
+
class Pip(TypedDict, total=False):
package_name: Required[str]
"""Pip package name"""
+ agent_setup: Optional[SequenceNotStr[str]]
+ """Setup commands to run after installation"""
+
pip_version: Optional[str]
"""Pip version constraint"""
diff --git a/tests/api_resources/test_agents.py b/tests/api_resources/test_agents.py
index 596338b85..6f8096491 100644
--- a/tests/api_resources/test_agents.py
+++ b/tests/api_resources/test_agents.py
@@ -33,17 +33,22 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
"type": "type",
"git": {
"repository": "repository",
+ "agent_setup": ["string"],
"ref": "ref",
- "setup": ["string"],
},
"npm": {
"package_name": "package_name",
+ "agent_setup": ["string"],
"npm_version": "npm_version",
"registry_url": "registry_url",
},
- "object": {"object_id": "object_id"},
+ "object": {
+ "object_id": "object_id",
+ "agent_setup": ["string"],
+ },
"pip": {
"package_name": "package_name",
+ "agent_setup": ["string"],
"pip_version": "pip_version",
"registry_url": "registry_url",
},
@@ -170,17 +175,22 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
"type": "type",
"git": {
"repository": "repository",
+ "agent_setup": ["string"],
"ref": "ref",
- "setup": ["string"],
},
"npm": {
"package_name": "package_name",
+ "agent_setup": ["string"],
"npm_version": "npm_version",
"registry_url": "registry_url",
},
- "object": {"object_id": "object_id"},
+ "object": {
+ "object_id": "object_id",
+ "agent_setup": ["string"],
+ },
"pip": {
"package_name": "package_name",
+ "agent_setup": ["string"],
"pip_version": "pip_version",
"registry_url": "registry_url",
},
diff --git a/tests/api_resources/test_blueprints.py b/tests/api_resources/test_blueprints.py
index 9826f0b67..5a28691d0 100644
--- a/tests/api_resources/test_blueprints.py
+++ b/tests/api_resources/test_blueprints.py
@@ -36,6 +36,13 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
+ build_contexts={
+ "foo": {
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ }
+ },
code_mounts=[
{
"repo_name": "repo_name",
@@ -65,6 +72,11 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
"username": "username",
},
},
+ local_build_context={
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ },
metadata={"foo": "string"},
secrets={"foo": "string"},
services=[
@@ -394,6 +406,13 @@ def test_method_preview_with_all_params(self, client: Runloop) -> None:
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
+ build_contexts={
+ "foo": {
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ }
+ },
code_mounts=[
{
"repo_name": "repo_name",
@@ -423,6 +442,11 @@ def test_method_preview_with_all_params(self, client: Runloop) -> None:
"username": "username",
},
},
+ local_build_context={
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ },
metadata={"foo": "string"},
secrets={"foo": "string"},
services=[
@@ -486,6 +510,13 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
+ build_contexts={
+ "foo": {
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ }
+ },
code_mounts=[
{
"repo_name": "repo_name",
@@ -515,6 +546,11 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
"username": "username",
},
},
+ local_build_context={
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ },
metadata={"foo": "string"},
secrets={"foo": "string"},
services=[
@@ -844,6 +880,13 @@ async def test_method_preview_with_all_params(self, async_client: AsyncRunloop)
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
+ build_contexts={
+ "foo": {
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ }
+ },
code_mounts=[
{
"repo_name": "repo_name",
@@ -873,6 +916,11 @@ async def test_method_preview_with_all_params(self, async_client: AsyncRunloop)
"username": "username",
},
},
+ local_build_context={
+ "type": "OBJECT",
+ "http": {"url": "url"},
+ "object": {"object_id": "object_id"},
+ },
metadata={"foo": "string"},
secrets={"foo": "string"},
services=[
From 07a0b8c1825c78b0a6c30c2d374b82aced2f97d5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 19 Nov 2025 00:17:30 +0000
Subject: [PATCH 09/11] chore(package): drop Python 3.8 support
From c87b986e558ad3a0cca2ad1609b9833baf86fef8 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 19 Nov 2025 00:22:13 +0000
Subject: [PATCH 10/11] feat(blueprints): Cleanup the BuildContext API
(#6407)\n\nTest
---
.stats.yml | 4 +-
.../resources/blueprints.py | 80 +++++++++----------
src/runloop_api_client/types/agent_view.py | 3 +
.../types/blueprint_build_parameters.py | 72 ++++-------------
.../types/blueprint_create_params.py | 72 ++++-------------
.../types/blueprint_preview_params.py | 72 ++++-------------
.../types/shared/agent_mount_parameters.py | 11 ++-
.../shared_params/agent_mount_parameters.py | 11 ++-
tests/api_resources/test_blueprints.py | 80 +++++++++----------
9 files changed, 150 insertions(+), 255 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 2ee72efab..33e553ff2 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 97
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-779f7a8b0be0c3d2d095c6256d35c5dbb4c28d049f3541384c51a8c215e8a87a.yml
-openapi_spec_hash: b4ebc80eeaf4e5b3bcd53c30433cf35e
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-5f33221208c1febba343daf570f73a5086f150a9b128df045ebddc3fe2c86607.yml
+openapi_spec_hash: 0aea07130ddbe43a665a13a68231e2ca
config_hash: 2363f563f42501d2b1587a4f64bdccaf
diff --git a/src/runloop_api_client/resources/blueprints.py b/src/runloop_api_client/resources/blueprints.py
index 8f2672da8..60d228522 100644
--- a/src/runloop_api_client/resources/blueprints.py
+++ b/src/runloop_api_client/resources/blueprints.py
@@ -131,13 +131,13 @@ def create(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
- build_contexts: Optional[Dict[str, blueprint_create_params.BuildContexts]] | Omit = omit,
+ build_context: Optional[blueprint_create_params.BuildContext] | 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,
- local_build_context: Optional[blueprint_create_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ named_build_contexts: Optional[Dict[str, blueprint_create_params.NamedBuildContexts]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
system_setup_commands: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -169,10 +169,7 @@ def create(
build_args: (Optional) Arbitrary Docker build args to pass during build.
- build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
- are typed context definitions (object or http). See Docker buildx additional
- contexts for details:
- https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ build_context: A build context backed by an Object.
code_mounts: A list of code mounts to be included in the Blueprint.
@@ -182,10 +179,13 @@ def create(
launch_parameters: Parameters to configure your Devbox at launch time.
- local_build_context: (Optional) Local build context stored in object-storage.
-
metadata: (Optional) User defined metadata for the Blueprint.
+ named_build_contexts: (Optional) Map of named build contexts to attach to the Blueprint build, where
+ the keys are the name used when referencing the contexts in a Dockerfile. See
+ Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
will be available to commands during the build. Secrets are NOT stored in the
blueprint image. Example: {"DB_PASS": "DATABASE_PASSWORD"} makes the secret
@@ -219,13 +219,13 @@ def create(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
- "build_contexts": build_contexts,
+ "build_context": build_context,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
- "local_build_context": local_build_context,
"metadata": metadata,
+ "named_build_contexts": named_build_contexts,
"secrets": secrets,
"services": services,
"system_setup_commands": system_setup_commands,
@@ -649,13 +649,13 @@ def preview(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
- build_contexts: Optional[Dict[str, blueprint_preview_params.BuildContexts]] | Omit = omit,
+ build_context: Optional[blueprint_preview_params.BuildContext] | 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,
- local_build_context: Optional[blueprint_preview_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ named_build_contexts: Optional[Dict[str, blueprint_preview_params.NamedBuildContexts]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_preview_params.Service]] | Omit = omit,
system_setup_commands: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -685,10 +685,7 @@ def preview(
build_args: (Optional) Arbitrary Docker build args to pass during build.
- build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
- are typed context definitions (object or http). See Docker buildx additional
- contexts for details:
- https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ build_context: A build context backed by an Object.
code_mounts: A list of code mounts to be included in the Blueprint.
@@ -698,10 +695,13 @@ def preview(
launch_parameters: Parameters to configure your Devbox at launch time.
- local_build_context: (Optional) Local build context stored in object-storage.
-
metadata: (Optional) User defined metadata for the Blueprint.
+ named_build_contexts: (Optional) Map of named build contexts to attach to the Blueprint build, where
+ the keys are the name used when referencing the contexts in a Dockerfile. See
+ Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
will be available to commands during the build. Secrets are NOT stored in the
blueprint image. Example: {"DB_PASS": "DATABASE_PASSWORD"} makes the secret
@@ -731,13 +731,13 @@ def preview(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
- "build_contexts": build_contexts,
+ "build_context": build_context,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
- "local_build_context": local_build_context,
"metadata": metadata,
+ "named_build_contexts": named_build_contexts,
"secrets": secrets,
"services": services,
"system_setup_commands": system_setup_commands,
@@ -782,13 +782,13 @@ async def create(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
- build_contexts: Optional[Dict[str, blueprint_create_params.BuildContexts]] | Omit = omit,
+ build_context: Optional[blueprint_create_params.BuildContext] | 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,
- local_build_context: Optional[blueprint_create_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ named_build_contexts: Optional[Dict[str, blueprint_create_params.NamedBuildContexts]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_create_params.Service]] | Omit = omit,
system_setup_commands: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -820,10 +820,7 @@ async def create(
build_args: (Optional) Arbitrary Docker build args to pass during build.
- build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
- are typed context definitions (object or http). See Docker buildx additional
- contexts for details:
- https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ build_context: A build context backed by an Object.
code_mounts: A list of code mounts to be included in the Blueprint.
@@ -833,10 +830,13 @@ async def create(
launch_parameters: Parameters to configure your Devbox at launch time.
- local_build_context: (Optional) Local build context stored in object-storage.
-
metadata: (Optional) User defined metadata for the Blueprint.
+ named_build_contexts: (Optional) Map of named build contexts to attach to the Blueprint build, where
+ the keys are the name used when referencing the contexts in a Dockerfile. See
+ Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
will be available to commands during the build. Secrets are NOT stored in the
blueprint image. Example: {"DB_PASS": "DATABASE_PASSWORD"} makes the secret
@@ -870,13 +870,13 @@ async def create(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
- "build_contexts": build_contexts,
+ "build_context": build_context,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
- "local_build_context": local_build_context,
"metadata": metadata,
+ "named_build_contexts": named_build_contexts,
"secrets": secrets,
"services": services,
"system_setup_commands": system_setup_commands,
@@ -1300,13 +1300,13 @@ async def preview(
base_blueprint_id: Optional[str] | Omit = omit,
base_blueprint_name: Optional[str] | Omit = omit,
build_args: Optional[Dict[str, str]] | Omit = omit,
- build_contexts: Optional[Dict[str, blueprint_preview_params.BuildContexts]] | Omit = omit,
+ build_context: Optional[blueprint_preview_params.BuildContext] | 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,
- local_build_context: Optional[blueprint_preview_params.LocalBuildContext] | Omit = omit,
metadata: Optional[Dict[str, str]] | Omit = omit,
+ named_build_contexts: Optional[Dict[str, blueprint_preview_params.NamedBuildContexts]] | Omit = omit,
secrets: Optional[Dict[str, str]] | Omit = omit,
services: Optional[Iterable[blueprint_preview_params.Service]] | Omit = omit,
system_setup_commands: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -1336,10 +1336,7 @@ async def preview(
build_args: (Optional) Arbitrary Docker build args to pass during build.
- build_contexts: (Optional) Map of named Docker build contexts. Keys are context names, values
- are typed context definitions (object or http). See Docker buildx additional
- contexts for details:
- https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ build_context: A build context backed by an Object.
code_mounts: A list of code mounts to be included in the Blueprint.
@@ -1349,10 +1346,13 @@ async def preview(
launch_parameters: Parameters to configure your Devbox at launch time.
- local_build_context: (Optional) Local build context stored in object-storage.
-
metadata: (Optional) User defined metadata for the Blueprint.
+ named_build_contexts: (Optional) Map of named build contexts to attach to the Blueprint build, where
+ the keys are the name used when referencing the contexts in a Dockerfile. See
+ Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+
secrets: (Optional) Map of mount IDs/environment variable names to secret names. Secrets
will be available to commands during the build. Secrets are NOT stored in the
blueprint image. Example: {"DB_PASS": "DATABASE_PASSWORD"} makes the secret
@@ -1382,13 +1382,13 @@ async def preview(
"base_blueprint_id": base_blueprint_id,
"base_blueprint_name": base_blueprint_name,
"build_args": build_args,
- "build_contexts": build_contexts,
+ "build_context": build_context,
"code_mounts": code_mounts,
"dockerfile": dockerfile,
"file_mounts": file_mounts,
"launch_parameters": launch_parameters,
- "local_build_context": local_build_context,
"metadata": metadata,
+ "named_build_contexts": named_build_contexts,
"secrets": secrets,
"services": services,
"system_setup_commands": system_setup_commands,
diff --git a/src/runloop_api_client/types/agent_view.py b/src/runloop_api_client/types/agent_view.py
index bf2520a49..77e56d1b8 100644
--- a/src/runloop_api_client/types/agent_view.py
+++ b/src/runloop_api_client/types/agent_view.py
@@ -12,6 +12,9 @@ class AgentView(BaseModel):
id: str
"""The unique identifier of the Agent."""
+ create_time_ms: int
+ """The creation time of the Agent (Unix timestamp milliseconds)."""
+
is_public: bool
"""Whether the Agent is publicly accessible."""
diff --git a/src/runloop_api_client/types/blueprint_build_parameters.py b/src/runloop_api_client/types/blueprint_build_parameters.py
index 25bac19d7..cc86468df 100644
--- a/src/runloop_api_client/types/blueprint_build_parameters.py
+++ b/src/runloop_api_client/types/blueprint_build_parameters.py
@@ -7,59 +7,21 @@
from .shared.launch_parameters import LaunchParameters
from .shared.code_mount_parameters import CodeMountParameters
-__all__ = [
- "BlueprintBuildParameters",
- "BuildContexts",
- "BuildContextsHTTP",
- "BuildContextsObject",
- "LocalBuildContext",
- "LocalBuildContextHTTP",
- "LocalBuildContextObject",
- "Service",
- "ServiceCredentials",
-]
+__all__ = ["BlueprintBuildParameters", "BuildContext", "NamedBuildContexts", "Service", "ServiceCredentials"]
-class BuildContextsHTTP(BaseModel):
- url: str
- """HTTP(S) URL to a tarball or directory to use as context."""
-
-
-class BuildContextsObject(BaseModel):
+class BuildContext(BaseModel):
object_id: str
- """Handle for a Runloop stored object to use as context."""
-
-
-class BuildContexts(BaseModel):
- type: Literal["OBJECT", "HTTP"]
- """Type of the context. Supported values: object, http"""
-
- http: Optional[BuildContextsHTTP] = None
- """HTTP(S) context parameters."""
+ """The ID of an object, whose contents are to be used as a build context."""
- object: Optional[BuildContextsObject] = None
- """Object context parameters (named build context)."""
+ type: Literal["object"]
-class LocalBuildContextHTTP(BaseModel):
- url: str
- """HTTP(S) URL to a tarball or directory to use as context."""
-
-
-class LocalBuildContextObject(BaseModel):
+class NamedBuildContexts(BaseModel):
object_id: str
- """Handle for a Runloop stored object to use as context."""
-
-
-class LocalBuildContext(BaseModel):
- type: Literal["OBJECT", "HTTP"]
- """Type of the context. Supported values: object, http"""
+ """The ID of an object, whose contents are to be used as a build context."""
- http: Optional[LocalBuildContextHTTP] = None
- """HTTP(S) context parameters."""
-
- object: Optional[LocalBuildContextObject] = None
- """Object context parameters (named build context)."""
+ type: Literal["object"]
class ServiceCredentials(BaseModel):
@@ -114,13 +76,8 @@ class BlueprintBuildParameters(BaseModel):
build_args: Optional[Dict[str, str]] = None
"""(Optional) Arbitrary Docker build args to pass during build."""
- build_contexts: Optional[Dict[str, BuildContexts]] = None
- """(Optional) Map of named Docker build contexts.
-
- Keys are context names, values are typed context definitions (object or http).
- See Docker buildx additional contexts for details:
- https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
- """
+ build_context: Optional[BuildContext] = None
+ """A build context backed by an Object."""
code_mounts: Optional[List[CodeMountParameters]] = None
"""A list of code mounts to be included in the Blueprint."""
@@ -134,12 +91,17 @@ class BlueprintBuildParameters(BaseModel):
launch_parameters: Optional[LaunchParameters] = None
"""Parameters to configure your Devbox at launch time."""
- local_build_context: Optional[LocalBuildContext] = None
- """(Optional) Local build context stored in object-storage."""
-
metadata: Optional[Dict[str, str]] = None
"""(Optional) User defined metadata for the Blueprint."""
+ named_build_contexts: Optional[Dict[str, NamedBuildContexts]] = None
+ """
+ (Optional) Map of named build contexts to attach to the Blueprint build, where
+ the keys are the name used when referencing the contexts in a Dockerfile. See
+ Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ """
+
secrets: Optional[Dict[str, str]] = None
"""(Optional) Map of mount IDs/environment variable names to secret names.
diff --git a/src/runloop_api_client/types/blueprint_create_params.py b/src/runloop_api_client/types/blueprint_create_params.py
index d2d94a3a8..a15e6f470 100644
--- a/src/runloop_api_client/types/blueprint_create_params.py
+++ b/src/runloop_api_client/types/blueprint_create_params.py
@@ -9,17 +9,7 @@
from .shared_params.launch_parameters import LaunchParameters
from .shared_params.code_mount_parameters import CodeMountParameters
-__all__ = [
- "BlueprintCreateParams",
- "BuildContexts",
- "BuildContextsHTTP",
- "BuildContextsObject",
- "LocalBuildContext",
- "LocalBuildContextHTTP",
- "LocalBuildContextObject",
- "Service",
- "ServiceCredentials",
-]
+__all__ = ["BlueprintCreateParams", "BuildContext", "NamedBuildContexts", "Service", "ServiceCredentials"]
class BlueprintCreateParams(TypedDict, total=False):
@@ -43,13 +33,8 @@ class BlueprintCreateParams(TypedDict, total=False):
build_args: Optional[Dict[str, str]]
"""(Optional) Arbitrary Docker build args to pass during build."""
- build_contexts: Optional[Dict[str, BuildContexts]]
- """(Optional) Map of named Docker build contexts.
-
- Keys are context names, values are typed context definitions (object or http).
- See Docker buildx additional contexts for details:
- https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
- """
+ build_context: Optional[BuildContext]
+ """A build context backed by an Object."""
code_mounts: Optional[Iterable[CodeMountParameters]]
"""A list of code mounts to be included in the Blueprint."""
@@ -63,12 +48,17 @@ class BlueprintCreateParams(TypedDict, total=False):
launch_parameters: Optional[LaunchParameters]
"""Parameters to configure your Devbox at launch time."""
- local_build_context: Optional[LocalBuildContext]
- """(Optional) Local build context stored in object-storage."""
-
metadata: Optional[Dict[str, str]]
"""(Optional) User defined metadata for the Blueprint."""
+ named_build_contexts: Optional[Dict[str, NamedBuildContexts]]
+ """
+ (Optional) Map of named build contexts to attach to the Blueprint build, where
+ the keys are the name used when referencing the contexts in a Dockerfile. See
+ Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ """
+
secrets: Optional[Dict[str, str]]
"""(Optional) Map of mount IDs/environment variable names to secret names.
@@ -88,46 +78,18 @@ class BlueprintCreateParams(TypedDict, total=False):
"""A list of commands to run to set up your system."""
-class BuildContextsHTTP(TypedDict, total=False):
- url: Required[str]
- """HTTP(S) URL to a tarball or directory to use as context."""
-
-
-class BuildContextsObject(TypedDict, total=False):
+class BuildContext(TypedDict, total=False):
object_id: Required[str]
- """Handle for a Runloop stored object to use as context."""
-
-
-class BuildContexts(TypedDict, total=False):
- type: Required[Literal["OBJECT", "HTTP"]]
- """Type of the context. Supported values: object, http"""
-
- http: Optional[BuildContextsHTTP]
- """HTTP(S) context parameters."""
-
- object: Optional[BuildContextsObject]
- """Object context parameters (named build context)."""
+ """The ID of an object, whose contents are to be used as a build context."""
+ type: Required[Literal["object"]]
-class LocalBuildContextHTTP(TypedDict, total=False):
- url: Required[str]
- """HTTP(S) URL to a tarball or directory to use as context."""
-
-class LocalBuildContextObject(TypedDict, total=False):
+class NamedBuildContexts(TypedDict, total=False):
object_id: Required[str]
- """Handle for a Runloop stored object to use as context."""
-
-
-class LocalBuildContext(TypedDict, total=False):
- type: Required[Literal["OBJECT", "HTTP"]]
- """Type of the context. Supported values: object, http"""
-
- http: Optional[LocalBuildContextHTTP]
- """HTTP(S) context parameters."""
+ """The ID of an object, whose contents are to be used as a build context."""
- object: Optional[LocalBuildContextObject]
- """Object context parameters (named build context)."""
+ type: Required[Literal["object"]]
class ServiceCredentials(TypedDict, total=False):
diff --git a/src/runloop_api_client/types/blueprint_preview_params.py b/src/runloop_api_client/types/blueprint_preview_params.py
index c58487655..81244126d 100644
--- a/src/runloop_api_client/types/blueprint_preview_params.py
+++ b/src/runloop_api_client/types/blueprint_preview_params.py
@@ -9,17 +9,7 @@
from .shared_params.launch_parameters import LaunchParameters
from .shared_params.code_mount_parameters import CodeMountParameters
-__all__ = [
- "BlueprintPreviewParams",
- "BuildContexts",
- "BuildContextsHTTP",
- "BuildContextsObject",
- "LocalBuildContext",
- "LocalBuildContextHTTP",
- "LocalBuildContextObject",
- "Service",
- "ServiceCredentials",
-]
+__all__ = ["BlueprintPreviewParams", "BuildContext", "NamedBuildContexts", "Service", "ServiceCredentials"]
class BlueprintPreviewParams(TypedDict, total=False):
@@ -43,13 +33,8 @@ class BlueprintPreviewParams(TypedDict, total=False):
build_args: Optional[Dict[str, str]]
"""(Optional) Arbitrary Docker build args to pass during build."""
- build_contexts: Optional[Dict[str, BuildContexts]]
- """(Optional) Map of named Docker build contexts.
-
- Keys are context names, values are typed context definitions (object or http).
- See Docker buildx additional contexts for details:
- https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
- """
+ build_context: Optional[BuildContext]
+ """A build context backed by an Object."""
code_mounts: Optional[Iterable[CodeMountParameters]]
"""A list of code mounts to be included in the Blueprint."""
@@ -63,12 +48,17 @@ class BlueprintPreviewParams(TypedDict, total=False):
launch_parameters: Optional[LaunchParameters]
"""Parameters to configure your Devbox at launch time."""
- local_build_context: Optional[LocalBuildContext]
- """(Optional) Local build context stored in object-storage."""
-
metadata: Optional[Dict[str, str]]
"""(Optional) User defined metadata for the Blueprint."""
+ named_build_contexts: Optional[Dict[str, NamedBuildContexts]]
+ """
+ (Optional) Map of named build contexts to attach to the Blueprint build, where
+ the keys are the name used when referencing the contexts in a Dockerfile. See
+ Docker buildx additional contexts for details:
+ https://docs.docker.com/reference/cli/docker/buildx/build/#build-context
+ """
+
secrets: Optional[Dict[str, str]]
"""(Optional) Map of mount IDs/environment variable names to secret names.
@@ -88,46 +78,18 @@ class BlueprintPreviewParams(TypedDict, total=False):
"""A list of commands to run to set up your system."""
-class BuildContextsHTTP(TypedDict, total=False):
- url: Required[str]
- """HTTP(S) URL to a tarball or directory to use as context."""
-
-
-class BuildContextsObject(TypedDict, total=False):
+class BuildContext(TypedDict, total=False):
object_id: Required[str]
- """Handle for a Runloop stored object to use as context."""
-
-
-class BuildContexts(TypedDict, total=False):
- type: Required[Literal["OBJECT", "HTTP"]]
- """Type of the context. Supported values: object, http"""
-
- http: Optional[BuildContextsHTTP]
- """HTTP(S) context parameters."""
-
- object: Optional[BuildContextsObject]
- """Object context parameters (named build context)."""
+ """The ID of an object, whose contents are to be used as a build context."""
+ type: Required[Literal["object"]]
-class LocalBuildContextHTTP(TypedDict, total=False):
- url: Required[str]
- """HTTP(S) URL to a tarball or directory to use as context."""
-
-class LocalBuildContextObject(TypedDict, total=False):
+class NamedBuildContexts(TypedDict, total=False):
object_id: Required[str]
- """Handle for a Runloop stored object to use as context."""
-
-
-class LocalBuildContext(TypedDict, total=False):
- type: Required[Literal["OBJECT", "HTTP"]]
- """Type of the context. Supported values: object, http"""
-
- http: Optional[LocalBuildContextHTTP]
- """HTTP(S) context parameters."""
+ """The ID of an object, whose contents are to be used as a build context."""
- object: Optional[LocalBuildContextObject]
- """Object context parameters (named build context)."""
+ type: Required[Literal["object"]]
class ServiceCredentials(TypedDict, total=False):
diff --git a/src/runloop_api_client/types/shared/agent_mount_parameters.py b/src/runloop_api_client/types/shared/agent_mount_parameters.py
index c2b384265..6351a19f3 100644
--- a/src/runloop_api_client/types/shared/agent_mount_parameters.py
+++ b/src/runloop_api_client/types/shared/agent_mount_parameters.py
@@ -9,8 +9,15 @@
class AgentMountParameters(BaseModel):
- agent_id: str
- """The ID of the agent to mount."""
+ agent_id: Optional[str] = None
+ """The ID of the agent to mount. Either agent_id or name must be set."""
+
+ agent_name: Optional[str] = None
+ """The name of the agent to mount.
+
+ Returns the most recent agent with a matching name if no agent id string
+ provided. Either agent id or name must be set
+ """
type: Literal["agent_mount"]
diff --git a/src/runloop_api_client/types/shared_params/agent_mount_parameters.py b/src/runloop_api_client/types/shared_params/agent_mount_parameters.py
index def126043..17c18dc32 100644
--- a/src/runloop_api_client/types/shared_params/agent_mount_parameters.py
+++ b/src/runloop_api_client/types/shared_params/agent_mount_parameters.py
@@ -9,8 +9,15 @@
class AgentMountParameters(TypedDict, total=False):
- agent_id: Required[str]
- """The ID of the agent to mount."""
+ agent_id: Required[Optional[str]]
+ """The ID of the agent to mount. Either agent_id or name must be set."""
+
+ agent_name: Required[Optional[str]]
+ """The name of the agent to mount.
+
+ Returns the most recent agent with a matching name if no agent id string
+ provided. Either agent id or name must be set
+ """
type: Required[Literal["agent_mount"]]
diff --git a/tests/api_resources/test_blueprints.py b/tests/api_resources/test_blueprints.py
index 5a28691d0..030e12112 100644
--- a/tests/api_resources/test_blueprints.py
+++ b/tests/api_resources/test_blueprints.py
@@ -36,12 +36,9 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
- build_contexts={
- "foo": {
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- }
+ build_context={
+ "object_id": "object_id",
+ "type": "object",
},
code_mounts=[
{
@@ -72,12 +69,13 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
"username": "username",
},
},
- local_build_context={
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- },
metadata={"foo": "string"},
+ named_build_contexts={
+ "foo": {
+ "object_id": "object_id",
+ "type": "object",
+ }
+ },
secrets={"foo": "string"},
services=[
{
@@ -406,12 +404,9 @@ def test_method_preview_with_all_params(self, client: Runloop) -> None:
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
- build_contexts={
- "foo": {
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- }
+ build_context={
+ "object_id": "object_id",
+ "type": "object",
},
code_mounts=[
{
@@ -442,12 +437,13 @@ def test_method_preview_with_all_params(self, client: Runloop) -> None:
"username": "username",
},
},
- local_build_context={
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- },
metadata={"foo": "string"},
+ named_build_contexts={
+ "foo": {
+ "object_id": "object_id",
+ "type": "object",
+ }
+ },
secrets={"foo": "string"},
services=[
{
@@ -510,12 +506,9 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
- build_contexts={
- "foo": {
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- }
+ build_context={
+ "object_id": "object_id",
+ "type": "object",
},
code_mounts=[
{
@@ -546,12 +539,13 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
"username": "username",
},
},
- local_build_context={
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- },
metadata={"foo": "string"},
+ named_build_contexts={
+ "foo": {
+ "object_id": "object_id",
+ "type": "object",
+ }
+ },
secrets={"foo": "string"},
services=[
{
@@ -880,12 +874,9 @@ async def test_method_preview_with_all_params(self, async_client: AsyncRunloop)
base_blueprint_id="base_blueprint_id",
base_blueprint_name="base_blueprint_name",
build_args={"foo": "string"},
- build_contexts={
- "foo": {
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- }
+ build_context={
+ "object_id": "object_id",
+ "type": "object",
},
code_mounts=[
{
@@ -916,12 +907,13 @@ async def test_method_preview_with_all_params(self, async_client: AsyncRunloop)
"username": "username",
},
},
- local_build_context={
- "type": "OBJECT",
- "http": {"url": "url"},
- "object": {"object_id": "object_id"},
- },
metadata={"foo": "string"},
+ named_build_contexts={
+ "foo": {
+ "object_id": "object_id",
+ "type": "object",
+ }
+ },
secrets={"foo": "string"},
services=[
{
From 87abab816e0277e1d2a5b39c36179eb1252b24bf Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 19 Nov 2025 00:22:30 +0000
Subject: [PATCH 11/11] release: 0.68.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 23 +++++++++++++++++++++++
pyproject.toml | 2 +-
src/runloop_api_client/_version.py | 2 +-
4 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index db00cae02..0b8a7c68d 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.67.0"
+ ".": "0.68.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8a9a7ad5..ae56707e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,28 @@
# Changelog
+## 0.68.0 (2025-11-19)
+
+Full Changelog: [v0.67.0...v0.68.0](https://github.com/runloopai/api-client-python/compare/v0.67.0...v0.68.0)
+
+### Features
+
+* **blueprints:** Cleanup the BuildContext API ([#6407](https://github.com/runloopai/api-client-python/issues/6407))\n\nTest ([c87b986](https://github.com/runloopai/api-client-python/commit/c87b986e558ad3a0cca2ad1609b9833baf86fef8))
+* **blueprints:** prevent deletion of blueprints with dependent snapshots ([ce55350](https://github.com/runloopai/api-client-python/commit/ce55350d81f7f5ba3a3aff8faea88c0e1366cea9))
+* **object:** Added ability to give objects a Time To Live, after which they are automatically deleted.\nfeat(blueprints): Added the ability to attach objects as build contexts that can be referenced in your Dockerfile. ([f2bc83c](https://github.com/runloopai/api-client-python/commit/f2bc83c126696aea224bb5978294fc3362a94eeb))
+
+
+### Bug Fixes
+
+* compat with Python 3.14 ([a52802a](https://github.com/runloopai/api-client-python/commit/a52802a6d12d96c3bf4bd670e77c9ec50d08b459))
+* **compat:** update signatures of `model_dump` and `model_dump_json` for Pydantic v1 ([50340b2](https://github.com/runloopai/api-client-python/commit/50340b20148f72cb645bba0bafde6f902e063425))
+* **snapshot:** added "deleted" status to DevboxSnapshotStatus enum \n fix(storage-object): added ObjectState enum, fixed createObject() to appropriately type content_type and state as the respective enums ([7c26593](https://github.com/runloopai/api-client-python/commit/7c265936088c074d00bd3c65b52dde5dcde3ccfb))
+
+
+### Chores
+
+* **package:** drop Python 3.8 support ([07a0b8c](https://github.com/runloopai/api-client-python/commit/07a0b8c1825c78b0a6c30c2d374b82aced2f97d5))
+* **package:** drop Python 3.8 support ([d67abf1](https://github.com/runloopai/api-client-python/commit/d67abf1c52a089e192987a261e69219d60514bc3))
+
## 0.67.0 (2025-11-14)
Full Changelog: [v0.66.1...v0.67.0](https://github.com/runloopai/api-client-python/compare/v0.66.1...v0.67.0)
diff --git a/pyproject.toml b/pyproject.toml
index 75e71661e..5b1f6ec4b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "runloop_api_client"
-version = "0.67.0"
+version = "0.68.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 d5ccb7242..03a1aaf1c 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.67.0" # x-release-please-version
+__version__ = "0.68.0" # x-release-please-version