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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
lint:
timeout-minutes: 10
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/dedalus-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -41,7 +41,7 @@ jobs:
permissions:
contents: read
id-token: write
runs-on: ${{ github.repository == 'stainless-sdks/dedalus-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

Expand Down Expand Up @@ -78,7 +78,7 @@ jobs:
test:
timeout-minutes: 10
name: test
runs-on: ${{ github.repository == 'stainless-sdks/dedalus-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.4.0"
".": "0.5.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: 32
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-a63ad804ae8ee532d57afae307595dae02d2a6924f83657430b3579193560775.yml
openapi_spec_hash: ccb02923079d91569a17162c88da590b
config_hash: 0e31b0b75cafdbc25febc2b7ca219799
configured_endpoints: 17
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-c0e28b234478af75f61bcf42f5f32818d96ec93b1d8239fa0ff1c801c0e4b64f.yml
openapi_spec_hash: a70c391bb0957fc90c5dbf251de8afe4
config_hash: fa45a5bf161b7291cb5ea20c2da83cc0
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Changelog

## 0.5.0 (2026-09-01)

Full Changelog: [v0.4.0...v0.5.0](https://github.com/dedalus-labs/dedalus-python/compare/v0.4.0...v0.5.0)

### ⚠ BREAKING CHANGES

* **api:** regenerate SDKs from the current public DCS contract

### Features

* **api:** regenerate SDKs from the current public DCS contract ([04208ef](https://github.com/dedalus-labs/dedalus-python/commit/04208ef05cb07426d68717abb57835e089b76205))
* **stlc:** configurable CI runner and private-production-repo support in workflow templates ([6acb1d3](https://github.com/dedalus-labs/dedalus-python/commit/6acb1d303d2a07cf6c01f63005a4f98541c47f40))


### Bug Fixes

* **auth:** prioritize first auth header ([81f3c28](https://github.com/dedalus-labs/dedalus-python/commit/81f3c288b2ae2e97046344177500714e1e4ce6be))
* **internal:** resolve build failures ([c10ce00](https://github.com/dedalus-labs/dedalus-python/commit/c10ce00180c146772ec9f390e3d058a1d9462082))


### Chores

* **internal:** allow the mock server port to be set with STAINLESS_MOCK_PORT ([aa8a0ee](https://github.com/dedalus-labs/dedalus-python/commit/aa8a0ee9f29ad6fa93a917baba1ab0ffaebb6959))

## 0.4.0 (2026-05-12)

Full Changelog: [v0.3.0...v0.4.0](https://github.com/dedalus-labs/dedalus-python/compare/v0.3.0...v0.4.0)
Expand Down
30 changes: 0 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,36 +118,6 @@ async def main() -> None:
asyncio.run(main())
```

## Streaming responses

We provide support for streaming responses using Server Side Events (SSE).

```python
from dedalus_sdk import Dedalus

client = Dedalus()

stream = client.machines.watch(
machine_id="dm-3",
)
for machine in stream:
print(machine.machine_id)
```

The async client uses the exact same interface.

```python
from dedalus_sdk import AsyncDedalus

client = AsyncDedalus()

stream = await client.machines.watch(
machine_id="dm-3",
)
async for machine in stream:
print(machine.machine_id)
```

## Using types

Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
Expand Down
79 changes: 2 additions & 77 deletions api.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
# Usage

Types:

```python
from dedalus_sdk.types import (
MachineComputeUsage,
MachineComputeUsageRow,
MachineStorageUsage,
MachineStorageUsageRow,
OrgUsage,
)
```

Methods:

- <code title="get /v1/usage">client.usage.<a href="./src/dedalus_sdk/resources/usage.py">retrieve</a>(\*\*<a href="src/dedalus_sdk/types/usage_retrieve_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/org_usage.py">OrgUsage</a></code>
- <code title="get /v1/usage/machines/compute">client.usage.<a href="./src/dedalus_sdk/resources/usage.py">machine_compute</a>(\*\*<a href="src/dedalus_sdk/types/usage_machine_compute_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machine_compute_usage.py">MachineComputeUsage</a></code>
- <code title="get /v1/usage/machines/storage">client.usage.<a href="./src/dedalus_sdk/resources/usage.py">machine_storage</a>(\*\*<a href="src/dedalus_sdk/types/usage_machine_storage_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machine_storage_usage.py">MachineStorageUsage</a></code>

# Machines

Types:
Expand All @@ -30,48 +10,19 @@ from dedalus_sdk.types import (
MachineList,
MachineListItem,
UpdateParams,
MachineRetrieveResponse,
)
```

Methods:

- <code title="post /v1/machines">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">create</a>(\*\*<a href="src/dedalus_sdk/types/machine_create_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machine.py">Machine</a></code>
- <code title="get /v1/machines/{machine_id}">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">retrieve</a>(\*, machine_id) -> <a href="./src/dedalus_sdk/types/machine.py">Machine</a></code>
- <code title="get /v1/machines/{machine_id}">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">retrieve</a>(\*, machine_id) -> <a href="./src/dedalus_sdk/types/machine_retrieve_response.py">MachineRetrieveResponse</a></code>
- <code title="patch /v1/machines/{machine_id}">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">update</a>(\*, machine_id, \*\*<a href="src/dedalus_sdk/types/machine_update_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machine.py">Machine</a></code>
- <code title="get /v1/machines">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">list</a>(\*\*<a href="src/dedalus_sdk/types/machine_list_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machine_list_item.py">SyncCursorPage[MachineListItem]</a></code>
- <code title="delete /v1/machines/{machine_id}">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">delete</a>(\*, machine_id) -> <a href="./src/dedalus_sdk/types/machine.py">Machine</a></code>
- <code title="post /v1/machines/{machine_id}/sleep">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">sleep</a>(\*, machine_id) -> <a href="./src/dedalus_sdk/types/machine.py">Machine</a></code>
- <code title="post /v1/machines/{machine_id}/wake">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">wake</a>(\*, machine_id) -> <a href="./src/dedalus_sdk/types/machine.py">Machine</a></code>
- <code title="get /v1/machines/{machine_id}/status/stream">client.machines.<a href="./src/dedalus_sdk/resources/machines/machines.py">watch</a>(\*, machine_id) -> <a href="./src/dedalus_sdk/types/machine.py">Machine</a></code>

## Artifacts

Types:

```python
from dedalus_sdk.types.machines import Artifact, ArtifactList
```

Methods:

- <code title="get /v1/machines/{machine_id}/artifacts/{artifact_id}">client.machines.artifacts.<a href="./src/dedalus_sdk/resources/machines/artifacts.py">retrieve</a>(\*, machine_id, artifact_id) -> <a href="./src/dedalus_sdk/types/machines/artifact.py">Artifact</a></code>
- <code title="get /v1/machines/{machine_id}/artifacts">client.machines.artifacts.<a href="./src/dedalus_sdk/resources/machines/artifacts.py">list</a>(\*, machine_id, \*\*<a href="src/dedalus_sdk/types/machines/artifact_list_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machines/artifact.py">SyncCursorPage[Artifact]</a></code>
- <code title="delete /v1/machines/{machine_id}/artifacts/{artifact_id}">client.machines.artifacts.<a href="./src/dedalus_sdk/resources/machines/artifacts.py">delete</a>(\*, machine_id, artifact_id) -> <a href="./src/dedalus_sdk/types/machines/artifact.py">Artifact</a></code>

## Previews

Types:

```python
from dedalus_sdk.types.machines import Preview, PreviewCreateParams, PreviewList
```

Methods:

- <code title="post /v1/machines/{machine_id}/previews">client.machines.previews.<a href="./src/dedalus_sdk/resources/machines/previews.py">create</a>(\*, machine_id, \*\*<a href="src/dedalus_sdk/types/machines/preview_create_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machines/preview.py">Preview</a></code>
- <code title="get /v1/machines/{machine_id}/previews/{preview_id}">client.machines.previews.<a href="./src/dedalus_sdk/resources/machines/previews.py">retrieve</a>(\*, machine_id, preview_id) -> <a href="./src/dedalus_sdk/types/machines/preview.py">Preview</a></code>
- <code title="get /v1/machines/{machine_id}/previews">client.machines.previews.<a href="./src/dedalus_sdk/resources/machines/previews.py">list</a>(\*, machine_id, \*\*<a href="src/dedalus_sdk/types/machines/preview_list_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machines/preview.py">SyncCursorPage[Preview]</a></code>
- <code title="delete /v1/machines/{machine_id}/previews/{preview_id}">client.machines.previews.<a href="./src/dedalus_sdk/resources/machines/previews.py">delete</a>(\*, machine_id, preview_id) -> <a href="./src/dedalus_sdk/types/machines/preview.py">Preview</a></code>

## SSH

Expand Down Expand Up @@ -118,29 +69,3 @@ Methods:
- <code title="delete /v1/machines/{machine_id}/executions/{execution_id}">client.machines.executions.<a href="./src/dedalus_sdk/resources/machines/executions.py">delete</a>(\*, machine_id, execution_id) -> <a href="./src/dedalus_sdk/types/machines/execution.py">Execution</a></code>
- <code title="get /v1/machines/{machine_id}/executions/{execution_id}/events">client.machines.executions.<a href="./src/dedalus_sdk/resources/machines/executions.py">events</a>(\*, machine_id, execution_id, \*\*<a href="src/dedalus_sdk/types/machines/execution_events_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machines/execution_event.py">SyncCursorPage[ExecutionEvent]</a></code>
- <code title="get /v1/machines/{machine_id}/executions/{execution_id}/output">client.machines.executions.<a href="./src/dedalus_sdk/resources/machines/executions.py">output</a>(\*, machine_id, execution_id) -> <a href="./src/dedalus_sdk/types/machines/execution_output.py">ExecutionOutput</a></code>

## Terminals

Types:

```python
from dedalus_sdk.types.machines import (
Terminal,
TerminalClientEvent,
TerminalClosedEvent,
TerminalCreateParams,
TerminalErrorEvent,
TerminalInputEvent,
TerminalList,
TerminalOutputEvent,
TerminalResizeEvent,
TerminalServerEvent,
)
```

Methods:

- <code title="post /v1/machines/{machine_id}/terminals">client.machines.terminals.<a href="./src/dedalus_sdk/resources/machines/terminals.py">create</a>(\*, machine_id, \*\*<a href="src/dedalus_sdk/types/machines/terminal_create_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machines/terminal.py">Terminal</a></code>
- <code title="get /v1/machines/{machine_id}/terminals/{terminal_id}">client.machines.terminals.<a href="./src/dedalus_sdk/resources/machines/terminals.py">retrieve</a>(\*, machine_id, terminal_id) -> <a href="./src/dedalus_sdk/types/machines/terminal.py">Terminal</a></code>
- <code title="get /v1/machines/{machine_id}/terminals">client.machines.terminals.<a href="./src/dedalus_sdk/resources/machines/terminals.py">list</a>(\*, machine_id, \*\*<a href="src/dedalus_sdk/types/machines/terminal_list_params.py">params</a>) -> <a href="./src/dedalus_sdk/types/machines/terminal.py">SyncCursorPage[Terminal]</a></code>
- <code title="delete /v1/machines/{machine_id}/terminals/{terminal_id}">client.machines.terminals.<a href="./src/dedalus_sdk/resources/machines/terminals.py">delete</a>(\*, machine_id, terminal_id) -> <a href="./src/dedalus_sdk/types/machines/terminal.py">Terminal</a></code>
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "dedalus-sdk"
version = "0.4.0"
version = "0.5.0"
description = "The official Python library for the Dedalus API"
dynamic = ["readme"]
license = "MIT"
Expand Down Expand Up @@ -42,7 +42,6 @@ Repository = "https://github.com/dedalus-labs/dedalus-python"

[project.optional-dependencies]
aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"]
websockets = ["websockets >= 13, < 16"]

[tool.uv]
managed = true
Expand Down
2 changes: 1 addition & 1 deletion scripts/lint
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ else
fi

echo "==> Running pyright"
uv run pyright
uv run pyright -p .

echo "==> Running mypy"
uv run mypy .
Expand Down
13 changes: 10 additions & 3 deletions scripts/mock
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ set -e

cd "$(dirname "$0")/.."

if [ "$1" == "--install" ]; then
npm exec --package=@stdy/cli@0.22.1 -- steady --version
exit 0
fi

if [[ -n "$1" && "$1" != '--'* ]]; then
URL="$1"
shift
Expand All @@ -20,16 +25,18 @@ fi
echo "==> Starting mock server with URL ${URL}"

# Run steady mock on the given spec
MOCK_PORT="${STAINLESS_MOCK_PORT:-4010}"

if [ "$1" == "--daemon" ]; then
# Pre-install the package so the download doesn't eat into the startup timeout
npm exec --package=@stdy/cli@0.22.1 -- steady --version

npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log &
npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p "$MOCK_PORT" --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log &

# Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
attempts=0
while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do
while ! curl --silent --fail "http://127.0.0.1:$MOCK_PORT/_x-steady/health" >/dev/null 2>&1; do
if ! kill -0 $! 2>/dev/null; then
echo
cat .stdy.log
Expand All @@ -48,5 +55,5 @@ if [ "$1" == "--daemon" ]; then

echo
else
npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL"
npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p "$MOCK_PORT" --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL"
fi
12 changes: 9 additions & 3 deletions scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color

MOCK_PORT="${STAINLESS_MOCK_PORT:-4010}"

function steady_is_running() {
curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1
curl --silent "http://127.0.0.1:$MOCK_PORT/_x-steady/health" >/dev/null 2>&1
}

kill_server_on_port() {
Expand All @@ -27,7 +29,7 @@ function is_overriding_api_base_url() {

if ! is_overriding_api_base_url && ! steady_is_running ; then
# When we exit this script, make sure to kill the background mock server process
trap 'kill_server_on_port 4010' EXIT
trap 'kill_server_on_port "$MOCK_PORT"' EXIT

# Start the dev server
./scripts/mock --daemon
Expand All @@ -43,7 +45,7 @@ elif ! steady_is_running ; then
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the steady command:"
echo
echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.22.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}"
echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.22.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p $MOCK_PORT --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}"
echo

exit 1
Expand All @@ -52,6 +54,10 @@ else
echo
fi

if [ -n "${STAINLESS_MOCK_PORT:-}" ] && ! is_overriding_api_base_url ; then
export TEST_API_BASE_URL="http://127.0.0.1:$MOCK_PORT"
fi

export DEFER_PYDANTIC_BUILD=false

# Note that we need to specify the patch version here so that uv
Expand Down
7 changes: 0 additions & 7 deletions src/dedalus_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,11 @@
AuthenticationError,
InternalServerError,
PermissionDeniedError,
WebSocketQueueFullError,
UnprocessableEntityError,
APIResponseValidationError,
WebSocketConnectionClosedError,
)
from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient
from ._utils._logs import setup_logging as _setup_logging
from .types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides

__all__ = [
"types",
Expand Down Expand Up @@ -74,10 +71,6 @@
"DefaultHttpxClient",
"DefaultAsyncHttpxClient",
"DefaultAioHttpClient",
"ReconnectingEvent",
"ReconnectingOverrides",
"WebSocketQueueFullError",
"WebSocketConnectionClosedError",
]

if not _t.TYPE_CHECKING:
Expand Down
Loading
Loading