Metadata-Version: 2.4
Name: crowddrop-sdk
Version: 0.1.0
Summary: CrowdDrop's SDK for embodied-agent hardware. This release covers cloud_brain: the LLM stays in the cloud, the device is a thin actuator/sensor bridge over Pub/Sub.
Project-URL: Repository, https://github.com/crowddrop-ai/crowddrop_ai_agents
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Provides-Extra: cloud-brain
Requires-Dist: crowddrop-pubsub-sdk<1.0.0,>=0.2.0; extra == "cloud-brain"
Requires-Dist: requests<3.0.0,>=2.28.0; extra == "cloud-brain"
Requires-Dist: google-auth<3.0.0,>=2.29.0; extra == "cloud-brain"

# crowddrop-sdk

CrowdDrop's SDK for connecting embodied-agent hardware to the CrowdDrop
platform. It splits into two architecturally different scenarios:

- **`cloud_brain`** (this release) - the LLM/tool-calling brain stays in
  CrowdDrop's cloud backend; your device is a thin actuator/sensor bridge
  over Google Cloud Pub/Sub. This is the right choice if your hardware can't
  run an LLM locally but can run a real Python process.
- **`edge_brain`** (planned, not yet released) - the LLM itself runs on your
  device. A different SDK surface entirely, for hardware with real local
  inference capacity.

If you're building a companion-computer-class device (e.g. Raspberry-Pi
class, full Linux + Python) that receives commands and reports telemetry,
you want the `cloud-brain` extra:

```bash
pip install "crowddrop-sdk[cloud-brain]"
```

This pulls in `crowddrop-pubsub-sdk` (CrowdDrop's Pub/Sub transport library)
as its only dependency - nothing else, so it stays light on constrained
hardware. The base `crowddrop-sdk` install (no extra) has no dependencies at
all.

## Getting credentials

There's no self-service signup. CrowdDrop issues one **agent device key**
per physical device, tied to the persona it embodies, and hands it to you
out-of-band along with the URL of the backend's token-vending endpoint. If
you don't have both yet, ask whoever set up your CrowdDrop persona - there's
no dashboard to generate one yourself. Your device never handles a raw GCP
service-account key file: it trades its device key for a short-lived GCP
access token by calling the token-vending endpoint (see
`cloud_brain/drone/edge_agent.py`'s `fetch_gcp_access_token`), and refreshes
that token automatically as it nears expiry.

## API reference (`cloud_brain`)

- **`crowddrop_sdk.cloud_brain.events.DRONE_COMMANDS`** - the eight
  supported movement primitives, each a fixed pulse with no
  duration/distance parameter: `take_off`, `land`, `forward`, `backward`,
  `strafe_left`, `strafe_right`, `turn_left`, `turn_right`.
- **`DroneCommandEvent(drone_id, command, issued_at, sequence)`** - what you
  receive, one per command.
- **`DroneTelemetryEvent(drone_id, latitude, longitude, heading,
  battery_level, reported_at, sequence)`** - what you publish back.
- **`crowddrop_sdk.cloud_brain.drone.channels.DroneCommandSubscriber`** -
  pull-based subscriber for commands (you always initiate the connection
  outward - nothing is ever pushed to your device).
- **`crowddrop_sdk.cloud_brain.drone.channels.DroneTelemetryPublisher`** -
  publisher for telemetry, with a `publish_telemetry(drone_id, latitude,
  longitude, heading, battery_level)` convenience method.
- **Two integration points you implement** - `handle_command(event)` (map
  each command to your real flight-controller call) and
  `read_battery_and_gps()` (return a real sensor reading). Both are stand-ins
  in the example below; this SDK doesn't know your hardware's API.

## Quickstart

See [`cloud_brain/drone/README.md`](crowddrop_sdk/cloud_brain/drone/README.md)
for a runnable example (`edge_agent.py`) and the exact env vars it needs.

## Releasing (publishing a new version to PyPI)

Releases are tag-triggered via `.github/workflows/publish-crowddrop-sdk.yml`,
using PyPI's **Trusted Publishing** (OIDC) — no API token is stored as a
GitHub secret.

1. Bump `version` in `crowddrop_sdk/pyproject.toml`.
2. Commit that change (on a branch, via the normal PR flow).
3. Once merged, tag the merge commit and push the tag:
   ```bash
   git tag crowddrop-sdk-v<version>   # e.g. crowddrop-sdk-v0.1.1
   git push origin crowddrop-sdk-v<version>
   ```
   The tag push is what fires the workflow — it builds `crowddrop_sdk/` and
   uploads it to [pypi.org/project/crowddrop-sdk](https://pypi.org/project/crowddrop-sdk/).
   No other trigger publishes this package.

If `cloud-brain`'s dependency on `crowddrop-pubsub-sdk` (see `pyproject.toml`)
needs bumping too, release `pubsub_sdk` first — see its own README's
"Releasing" section, same mechanism, separate workflow/tag prefix
(`pubsub-sdk-v*`).

**One-time setup, not yet done as of this writing — needed before the first
tag push, and again only if this ever moves to a different PyPI
account/org:**
- Register a **pending publisher** for `crowddrop-sdk` at
  https://pypi.org/manage/account/publishing/ — this can be done before the
  PyPI project exists, so it covers the *first-ever* release too, not just
  subsequent ones. Fill in: PyPI project name `crowddrop-sdk`, repo owner
  `crowddrop-ai`, repo name `crowddrop_ai_agents`, workflow filename
  `publish-crowddrop-sdk.yml`, environment name `pypi`. Requires a PyPI
  account with 2FA enabled — no API token to generate or store.
- The `pypi` GitHub Environment referenced by the workflow is created
  automatically the first time the workflow runs against it; create it
  manually in this repo's Settings → Environments beforehand only if you
  want a required-reviewer protection rule (so a tag push pauses for human
  approval before it actually publishes).
- `../scripts/publish_python_packages.sh` (manual `build` + `twine upload`)
  is kept as a fallback/local-dry-run tool only — with a pending publisher
  registered, it's no longer needed even for the first release.

Versioning is manual — nothing cross-checks the tag against
`pyproject.toml`'s `version`. Bump the file first, commit, *then* tag that
exact commit; tagging a commit whose `pyproject.toml` still has an
already-published version will fail the upload (PyPI rejects re-uploading an
existing version).
