Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.28.0"
".": "1.29.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 1.29.0 (2026-08-10)

Full Changelog: [v1.28.0...v1.29.0](https://github.com/runloopai/api-client-python/compare/v1.28.0...v1.29.0)

### Features

* **axon:** add registry delete endpoint ([#10769](https://github.com/runloopai/api-client-python/issues/10769)) ([c63f011](https://github.com/runloopai/api-client-python/commit/c63f01108d98785b358357e4e65e5e517dd0805e))
* **broker:** plumb Pi protocol selection ([#10256](https://github.com/runloopai/api-client-python/issues/10256)) ([974d52b](https://github.com/runloopai/api-client-python/commit/974d52b8743ceda8a7127e3a3432ce51e71b1bfd))
* **converter:** add Helm chart, container image, and enable in dev ([#10405](https://github.com/runloopai/api-client-python/issues/10405)) ([0d5ca34](https://github.com/runloopai/api-client-python/commit/0d5ca3438ac4cbcafdfaf7584042bd78a956e3ae))
* **devbox:** recover resume provisioning failures ([#10597](https://github.com/runloopai/api-client-python/issues/10597)) ([518301e](https://github.com/runloopai/api-client-python/commit/518301e444b95bc5fa73cc0f13be67cf3f750024))

## 1.28.0 (2026-07-29)

Full Changelog: [v1.27.0...v1.28.0](https://github.com/runloopai/api-client-python/compare/v1.27.0...v1.28.0)
Expand Down
1 change: 1 addition & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ Methods:
- <code title="post /v1/axons">client.axons.<a href="./src/runloop_api_client/resources/axons/axons.py">create</a>(\*\*<a href="src/runloop_api_client/types/axon_create_params.py">params</a>) -> <a href="./src/runloop_api_client/types/axon_view.py">AxonView</a></code>
- <code title="get /v1/axons/{id}">client.axons.<a href="./src/runloop_api_client/resources/axons/axons.py">retrieve</a>(id) -> <a href="./src/runloop_api_client/types/axon_view.py">AxonView</a></code>
- <code title="get /v1/axons">client.axons.<a href="./src/runloop_api_client/resources/axons/axons.py">list</a>(\*\*<a href="src/runloop_api_client/types/axon_list_params.py">params</a>) -> <a href="./src/runloop_api_client/types/axon_view.py">SyncAxonsCursorIDPage[AxonView]</a></code>
- <code title="delete /v1/axons/{id}">client.axons.<a href="./src/runloop_api_client/resources/axons/axons.py">delete</a>(id) -> object</code>
- <code title="post /v1/axons/{id}/publish">client.axons.<a href="./src/runloop_api_client/resources/axons/axons.py">publish</a>(id, \*\*<a href="src/runloop_api_client/types/axon_publish_params.py">params</a>) -> <a href="./src/runloop_api_client/types/publish_result_view.py">PublishResultView</a></code>
- <code title="get /v1/axons/{id}/subscribe/sse">client.axons.<a href="./src/runloop_api_client/resources/axons/axons.py">subscribe_sse</a>(id, \*\*<a href="src/runloop_api_client/types/axon_subscribe_sse_params.py">params</a>) -> <a href="./src/runloop_api_client/types/axon_event_view.py">AxonEventView</a></code>

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "runloop_api_client"
version = "1.28.0"
version = "1.29.0"
description = "The official Python library for the runloop API"
dynamic = ["readme"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion src/runloop_api_client/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "runloop_api_client"
__version__ = "1.28.0" # x-release-please-version
__version__ = "1.29.0" # x-release-please-version
92 changes: 92 additions & 0 deletions src/runloop_api_client/resources/axons/axons.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
)
Expand Down Expand Up @@ -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,
)
Expand Down Expand Up @@ -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,
)
Expand Down Expand Up @@ -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,
)
Expand Down
2 changes: 1 addition & 1 deletion src/runloop_api_client/types/blueprint_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/runloop_api_client/types/devbox_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 5 additions & 3 deletions src/runloop_api_client/types/shared/broker_mount.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions src/runloop_api_client/types/shared_params/broker_mount.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
76 changes: 76 additions & 0 deletions tests/api_resources/test_axons.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down