Skip to content
Merged
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
92 changes: 92 additions & 0 deletions .claude/skills/dedalus-python-sdk/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
name: dedalus-python-sdk
description: "Python SDK for Dedalus API. Use when writing Python code that calls Dedalus API with the dedalus-sdk package: installing it, constructing and authenticating the client, and calling API operations."
---

# Dedalus Python SDK

Generated Python client for Dedalus API, published as `dedalus-sdk`. Use the generated client instead of hand-writing HTTP requests.

## Install

```sh
pip install dedalus-sdk
```

## Client setup and authentication

```python
import os

from dedalus_sdk import Dedalus

client = Dedalus(
x_api_key=os.environ.get("DEDALUS_X_API_KEY"),
)
```

Provide credentials using the options below. Environment variables are read automatically when the target runtime supports them:

- `x_api_key` (env: `DEDALUS_X_API_KEY`) — Dedalus API key. Alternative to Bearer token.
- `api_key` (env: `DEDALUS_API_KEY`) — Dedalus API key or short-lived delegated access token in Authorization: Bearer <credential>.

## Calling operations

```python
import os

from dedalus_sdk import Dedalus

client = Dedalus(
x_api_key=os.environ.get("DEDALUS_X_API_KEY"),
)

machine = client.machines.create(
autosleep="300s",
memory_mib=4096,
storage_gib=10,
vcpu=1,
idempotency_key="",
)

print(machine.machine_id)
```

Method names, parameter shapes, and response types are generated from the API description — do not guess them. Look up the exact call signature in [api.md](../../../api.md) before writing a call.

## Pagination

List endpoints return paginated results you can iterate directly; the SDK fetches subsequent pages for you.

```python
page = client.machines.list()
```

## Error handling

Non-success responses throw generated API errors. Error objects expose status, headers, response body, and request metadata where the target runtime supports it.

```python
from dedalus_sdk import APIStatusError

try:
machine = client.machines.create(
autosleep="300s",
memory_mib=4096,
storage_gib=10,
vcpu=1,
idempotency_key="",
)
except APIStatusError as err:
print(err.status_code, err.message)
raise
```

## Requirements

- Python 3.8 or newer

## Reference files

- [README.md](../../../README.md) — full feature tour: client options, retries and timeouts, logging.
- [api.md](../../../api.md) — complete catalogue of every operation with request and response types.
8 changes: 0 additions & 8 deletions .devcontainer/Dockerfile

This file was deleted.

43 changes: 0 additions & 43 deletions .devcontainer/devcontainer.json

This file was deleted.

4 changes: 0 additions & 4 deletions .github/CODEOWNERS

This file was deleted.

95 changes: 0 additions & 95 deletions .github/workflows/ci.yml

This file was deleted.

30 changes: 0 additions & 30 deletions .github/workflows/publish-pypi.yml

This file was deleted.

102 changes: 102 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Release Please

on:
# A release is cut when a human merges the platform-managed release PR into
# main (the PR's base, so its diff shows the full pending release).
# Every other push here runs release-please as well — commits written straight to
# this branch included — and cuts nothing, there being no release commit at the tip.
push:
branches:
- main
# The Scalar platform pushes these workflow files straight to main to keep them
# current between releases; that is bookkeeping, never a release. Running anyway is worse
# than pointless on a branch that has not been handed a .release-please-manifest.json yet —
# release-please fails the run outright when it cannot read one. A release commit always
# rewrites the manifest and the changelog, so this filter can never swallow one.
paths-ignore:
- '.github/workflows/**'
# Manual fallback only; nothing in the automated chain depends on dispatch.
workflow_dispatch:

permissions:
contents: write
# Required to update the merged release PR's autorelease labels after tagging.
pull-requests: write

jobs:
release-please:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
# Consumed by the publish job's checkout: without this mapping the checkout ref would be
# empty and the publish would build the triggering branch head instead of the released
# tag's exact commit.
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
id: release
with:
target-branch: main
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# Release PRs are opened and updated by the Scalar platform with its own
# credential (so their CI runs without manual approval); this workflow only
# cuts the tag + GitHub Release once a release PR is merged.
skip-github-pull-request: true
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
if: ${{ steps.release.outputs.release_created == 'true' }}
with:
fetch-depth: 0
# Merging the release PR into main is itself the promotion, but the
# version bump and changelog must also land back on scalar-next, or the next
# release PR would propose this release again. A real merge (never a plain
# commit push) so a squash- or rebase-merged release PR syncs just as well; the
# non-conventional message keeps the sync commit out of future changelogs. Plain
# (non-force) push on purpose: losing a race against a concurrent regeneration
# push fails loudly here, and the platform's next sync re-converges.
- name: Sync release back to scalar-next
if: ${{ steps.release.outputs.release_created == 'true' }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git fetch origin scalar-next
git checkout -B scalar-next origin/scalar-next
git merge --no-edit -m "Sync release ${{ steps.release.outputs.tag_name }} back to scalar-next" "${{ steps.release.outputs.sha }}"
git push origin scalar-next
publish:
needs: release-please
# `!cancelled()` keeps publishing even when the back-sync to the integration branch
# failed: a raced integration branch must not block the release from reaching its
# registry.
if: ${{ !cancelled() && needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
environment: production
# Job-level permissions replace the workflow's release-cutting grants with the publish
# floor. OIDC trusted publishing verifies this run's claims, which name this workflow
# file — register release-please.yml as the trusted publisher on the registry.
permissions:
contents: read
id-token: write
packages: write
env:
VERSIONING_POLICY: manual
steps:
# Publishing runs inline — a top-level job of this same run — rather than dispatching
# sdk-release.yml: workflow_dispatch resolves the target workflow on the repository's
# default branch only, so a dispatch would 404 whenever the release line is any other
# branch, while OIDC trusted publishing accepts this job because it stays top-level
# (never a reusable-workflow call). The release-please job cut the tag earlier in this
# run; checking it out publishes exactly the released commit, not the branch head that
# triggered the workflow.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
- run: python -m pip install --upgrade build
- run: python -m build
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
skip-existing: true
Loading
Loading