diff --git a/.stats.yml b/.stats.yml
index 63705699e..02013546c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 120
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai/runloop-c1b0e0d2c2bf9d7888ddef0cfdfb390458875cd2c1feb48a06fcd06e92105326.yml
-openapi_spec_hash: ec61cf6d205251b54e1a6d68d9dd9860
-config_hash: 6d102da8b9fcc3d0deb42d7a707e78c6
+configured_endpoints: 121
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai/runloop-a9327279b1ba17f0983d92a3065b04a2bc1b5e5e830cf099aef4f79072fe4075.yml
+openapi_spec_hash: b63815af36cf18c8cc70be416f9c0f71
+config_hash: 2b0535779b180339d10766ba74a96700
diff --git a/api.md b/api.md
index 6becb60c5..584c2d2f8 100644
--- a/api.md
+++ b/api.md
@@ -131,6 +131,7 @@ Methods:
- client.axons.create(\*\*params) -> AxonView
- client.axons.retrieve(id) -> AxonView
- client.axons.list(\*\*params) -> SyncAxonsCursorIDPage[AxonView]
+- client.axons.delete(id) -> object
- client.axons.publish(id, \*\*params) -> PublishResultView
- client.axons.subscribe_sse(id, \*\*params) -> AxonEventView
diff --git a/src/runloop_api_client/resources/axons/axons.py b/src/runloop_api_client/resources/axons/axons.py
index fba62a339..232f6f4c2 100644
--- a/src/runloop_api_client/resources/axons/axons.py
+++ b/src/runloop_api_client/resources/axons/axons.py
@@ -210,6 +210,46 @@ def list(
model=AxonView,
)
+ def delete(
+ 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,
+ idempotency_key: str | None = None,
+ ) -> object:
+ """
+ [Beta] Mark an axon deleted.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._delete(
+ path_template("/v1/axons/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=object,
+ )
+
def publish(
self,
id: str,
@@ -485,6 +525,46 @@ def list(
model=AxonView,
)
+ async def delete(
+ 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,
+ idempotency_key: str | None = None,
+ ) -> object:
+ """
+ [Beta] Mark an axon deleted.
+
+ 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
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._delete(
+ path_template("/v1/axons/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=object,
+ )
+
async def publish(
self,
id: str,
@@ -607,6 +687,9 @@ def __init__(self, axons: AxonsResource) -> None:
self.list = to_raw_response_wrapper(
axons.list,
)
+ self.delete = to_raw_response_wrapper(
+ axons.delete,
+ )
self.publish = to_raw_response_wrapper(
axons.publish,
)
@@ -636,6 +719,9 @@ def __init__(self, axons: AsyncAxonsResource) -> None:
self.list = async_to_raw_response_wrapper(
axons.list,
)
+ self.delete = async_to_raw_response_wrapper(
+ axons.delete,
+ )
self.publish = async_to_raw_response_wrapper(
axons.publish,
)
@@ -665,6 +751,9 @@ def __init__(self, axons: AxonsResource) -> None:
self.list = to_streamed_response_wrapper(
axons.list,
)
+ self.delete = to_streamed_response_wrapper(
+ axons.delete,
+ )
self.publish = to_streamed_response_wrapper(
axons.publish,
)
@@ -694,6 +783,9 @@ def __init__(self, axons: AsyncAxonsResource) -> None:
self.list = async_to_streamed_response_wrapper(
axons.list,
)
+ self.delete = async_to_streamed_response_wrapper(
+ axons.delete,
+ )
self.publish = async_to_streamed_response_wrapper(
axons.publish,
)
diff --git a/src/runloop_api_client/types/blueprint_view.py b/src/runloop_api_client/types/blueprint_view.py
index 87c1eecab..b0bfefecd 100644
--- a/src/runloop_api_client/types/blueprint_view.py
+++ b/src/runloop_api_client/types/blueprint_view.py
@@ -63,7 +63,7 @@ class BlueprintView(BaseModel):
state: Literal["created", "deleted"]
"""The state of the Blueprint."""
- status: Literal["queued", "provisioning", "building", "failed", "build_complete"]
+ status: Literal["queued", "provisioning", "building", "awaiting_upload", "failed", "build_complete"]
"""The status of the Blueprint build."""
base_blueprint_id: Optional[str] = None
diff --git a/src/runloop_api_client/types/devbox_view.py b/src/runloop_api_client/types/devbox_view.py
index 49ffc1ec8..504d1fe2e 100644
--- a/src/runloop_api_client/types/devbox_view.py
+++ b/src/runloop_api_client/types/devbox_view.py
@@ -11,6 +11,9 @@
class StateTransition(BaseModel):
+ failure_reason: Optional[str] = None
+ """The failure that caused this state transition, if applicable."""
+
status: Optional[
Literal[
"scheduled",
diff --git a/src/runloop_api_client/types/shared/broker_mount.py b/src/runloop_api_client/types/shared/broker_mount.py
index adf49c04a..97e6c940a 100644
--- a/src/runloop_api_client/types/shared/broker_mount.py
+++ b/src/runloop_api_client/types/shared/broker_mount.py
@@ -17,16 +17,18 @@ class BrokerMount(BaseModel):
agent_binary: Optional[str] = None
"""Binary to launch the agent (e.g., 'opencode').
- Used by protocols that launch a subprocess (acp, claude_json, codex_json).
+ Used by protocols that launch a subprocess (acp, claude_json, codex_json,
+ pi_json).
"""
launch_args: Optional[List[str]] = None
"""Arguments to pass to the agent command (e.g., ['acp']).
- Used by protocols that launch a subprocess (acp, claude_json, codex_json).
+ Used by protocols that launch a subprocess (acp, claude_json, codex_json,
+ pi_json).
"""
- protocol: Optional[Literal["acp", "claude_json", "codex_json"]] = None
+ protocol: Optional[Literal["acp", "claude_json", "codex_json", "pi_json"]] = None
"""The protocol used by the broker to deliver events to the agent."""
working_directory: Optional[str] = None
diff --git a/src/runloop_api_client/types/shared_params/broker_mount.py b/src/runloop_api_client/types/shared_params/broker_mount.py
index e62bd59e5..55e6b6661 100644
--- a/src/runloop_api_client/types/shared_params/broker_mount.py
+++ b/src/runloop_api_client/types/shared_params/broker_mount.py
@@ -19,16 +19,18 @@ class BrokerMount(TypedDict, total=False):
agent_binary: Optional[str]
"""Binary to launch the agent (e.g., 'opencode').
- Used by protocols that launch a subprocess (acp, claude_json, codex_json).
+ Used by protocols that launch a subprocess (acp, claude_json, codex_json,
+ pi_json).
"""
launch_args: Optional[SequenceNotStr[str]]
"""Arguments to pass to the agent command (e.g., ['acp']).
- Used by protocols that launch a subprocess (acp, claude_json, codex_json).
+ Used by protocols that launch a subprocess (acp, claude_json, codex_json,
+ pi_json).
"""
- protocol: Optional[Literal["acp", "claude_json", "codex_json"]]
+ protocol: Optional[Literal["acp", "claude_json", "codex_json", "pi_json"]]
"""The protocol used by the broker to deliver events to the agent."""
working_directory: Optional[str]
diff --git a/tests/api_resources/test_axons.py b/tests/api_resources/test_axons.py
index 8764443bb..97f4f663c 100644
--- a/tests/api_resources/test_axons.py
+++ b/tests/api_resources/test_axons.py
@@ -128,6 +128,44 @@ def test_streaming_response_list(self, client: Runloop) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_delete(self, client: Runloop) -> None:
+ axon = client.axons.delete(
+ "id",
+ )
+ assert_matches_type(object, axon, path=["response"])
+
+ @parametrize
+ def test_raw_response_delete(self, client: Runloop) -> None:
+ response = client.axons.with_raw_response.delete(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ axon = response.parse()
+ assert_matches_type(object, axon, path=["response"])
+
+ @parametrize
+ def test_streaming_response_delete(self, client: Runloop) -> None:
+ with client.axons.with_streaming_response.delete(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ axon = response.parse()
+ assert_matches_type(object, axon, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_delete(self, client: Runloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.axons.with_raw_response.delete(
+ "",
+ )
+
@parametrize
def test_method_publish(self, client: Runloop) -> None:
axon = client.axons.publish(
@@ -340,6 +378,44 @@ async def test_streaming_response_list(self, async_client: AsyncRunloop) -> None
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncRunloop) -> None:
+ axon = await async_client.axons.delete(
+ "id",
+ )
+ assert_matches_type(object, axon, path=["response"])
+
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncRunloop) -> None:
+ response = await async_client.axons.with_raw_response.delete(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ axon = await response.parse()
+ assert_matches_type(object, axon, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncRunloop) -> None:
+ async with async_client.axons.with_streaming_response.delete(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ axon = await response.parse()
+ assert_matches_type(object, axon, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_delete(self, async_client: AsyncRunloop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.axons.with_raw_response.delete(
+ "",
+ )
+
@parametrize
async def test_method_publish(self, async_client: AsyncRunloop) -> None:
axon = await async_client.axons.publish(