Metadata-Version: 2.4
Name: botmanifold
Version: 0.3.1
Summary: Official Python SDK for BotManifold - Robot Policy Verification & Competition Platform
Author-email: Bot Manifold <admin@botmanifold.com>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://botmanifold.com
Project-URL: Documentation, https://docs.botmanifold.com
Project-URL: Repository, https://github.com/botmanifold/botmanifold-python
Project-URL: Issues, https://github.com/botmanifold/botmanifold-python/issues
Keywords: robotics,verification,safety,competition
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31.0
Requires-Dist: click>=8.0
Requires-Dist: numpy>=2.2.6
Requires-Dist: fastapi>=0.110.0
Requires-Dist: uvicorn>=0.27.0
Requires-Dist: websockets>=13.0
Requires-Dist: pydantic>=2.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: serve
Requires-Dist: uvicorn>=0.20.0; extra == "serve"
Provides-Extra: async
Requires-Dist: httpx[http2]>=0.27.0; extra == "async"
Requires-Dist: httpx-sse>=0.4.0; extra == "async"
Provides-Extra: bridge
Requires-Dist: mujoco>=3.1.1; extra == "bridge"
Requires-Dist: lerobot[feetech]==0.4.3; extra == "bridge"
Requires-Dist: pymycobot==4.0.7; extra == "bridge"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: pyyaml>=6.0; extra == "dev"
Dynamic: license-file

# BotManifold SDK

Official Python SDK and CLI for [BotManifold](https://botmanifold.com): verify robot policies in
simulation, manage datasets and training jobs, and run the teleop bridge for real arms.

## Installation

```bash
pip install botmanifold
```

Optional extras:

| Extra | Adds | For |
|:------|:-----|:----|
| `async` | `httpx[http2]`, `httpx-sse` | `AsyncBotManifoldClient` |
| `serve` | `uvicorn` | `botmanifold serve` |
| `bridge` | `mujoco`, `lerobot[feetech]`, `pymycobot` | the local teleop bridge (`botmanifold bridge ...`) |
| `dev` | pytest, ruff | development |

```bash
pip install "botmanifold[bridge]"
```

The `bridge` extra pulls in `lerobot` and its dependencies (`torch`, `opencv-python-headless`,
...). The base install is a lightweight API client; verify users never pay for it.

## Quick start

```python
from botmanifold import BotManifoldClient

client = BotManifoldClient(api_key="bm_...")

report = client.verify.run("my_policy.zip", scenario="messy_room")
print(report.verdict)   # Verdict.SAFE, Verdict.UNSAFE or Verdict.ERROR
print(report.score)
```

## CLI

```bash
botmanifold --help

# Verify a policy (a ZIP, or a running policy server)
botmanifold verify my_policy.zip --scenario messy_room
botmanifold verify --url http://localhost:8765 --scenario messy_room

# Local development
botmanifold serve my_policy.py --port 8765          # serve a policy over HTTP
botmanifold mock-server episode.jsonl --port 8765   # replay recorded episodes

# Datasets and scenarios
botmanifold datasets list
botmanifold datasets quality <dataset_id>
botmanifold datasets episodes <dataset_id>
botmanifold scenario validate <scenario>

# Managed training jobs
botmanifold train submit ...
botmanifold train status <job_id>      # also: list, logs, cancel, set-provider

# Teleop bridge for real arms (needs the `bridge` extra)
botmanifold bridge serve ...           # also: teleop, upload, sessions, robots, pair, resume,
                                       # jog, control-take, confirm-calibration,
                                       # confirm-diagnostics, confirm-leader-web
```

Run any command with `--help` for its options.

## Async usage

```python
import asyncio
from botmanifold import AsyncBotManifoldClient

async def main() -> None:
    async with AsyncBotManifoldClient(api_key="bm_...") as client:
        report = await client.verify.run("my_policy.zip", scenario="messy_room")
        print(report.verdict)

asyncio.run(main())
```

## API reference

### Client

```python
client = BotManifoldClient(
    api_key="...",      # or set BOTMANIFOLD_API_KEY
    base_url="...",     # optional, defaults to production; or BOTMANIFOLD_API_URL
    timeout=30,         # request timeout in seconds
)
```

The client exposes `verify`, `training` and `pipeline`.

### `client.verify`

```python
# Verify a policy file and wait for the result
report = client.verify.run(policy="policy.zip", scenario="messy_room", num_episodes=5, timeout=300)

# Or verify a running policy server
report = client.verify.run(policy_url="http://localhost:8765", scenario="messy_room")

if report.is_safe:
    print("Policy is safe")

# Non-blocking
report = client.verify.run("policy.zip", scenario="messy_room", wait=False)
final = client.verify.wait(report.job_id)

# Poll an existing job
status = client.verify.status(job_id)
```

### `client.training`

Training runs, checkpoints and managed jobs: `list_runs`, `get_run`, `list_checkpoints`,
`get_convergence_status`, `submit_job`, `get_job`, `list_jobs`, `cancel_job`, `get_job_logs`,
`set_gpu_provider`, and the reporting calls `report_metrics`, `report_gpu`,
`register_checkpoint`. Reporting needs `BOTMANIFOLD_TRAINING_API_KEY`. The Training Monitor
service these talk to is not deployed in staging or production.

### `client.pipeline`

Dataset management: `list_datasets`, `get_dataset_quality`, `list_episodes`,
`exclude_episodes`.

### Hardware

```python
bundles = client.get("/api/hardware/bundles")
for b in bundles["bundles"]:
    print(f"{b['name']} - ${b['price_cents'] / 100:,.2f}")
```

See [`examples/hardware_quickstart.py`](examples/hardware_quickstart.py).

## Teleop bridge

`botmanifold.bridge` is the local agent that drives an arm (SO-100, myCobot 280), records
demonstration episodes as LeRobot datasets, uploads them, and talks to the Studio Teleop
panel over WebSocket (directly or through `services/teleop_relay`). It also hosts the myCobot
diagnostics checks. The setup guides are in `docs/guides/`.

## Environment variables

| Variable | Description |
|:---------|:------------|
| `BOTMANIFOLD_API_KEY` | API key for authentication |
| `BOTMANIFOLD_API_URL` | Custom API base URL |
| `BOTMANIFOLD_TRAINING_API_KEY` | API key for training reporting calls |

## Development

```bash
# From the repository root (a plain `uv sync` removes this package)
uv sync --all-packages --all-groups --all-extras

uv run pytest sdk/python/tests -q
uv run ruff check sdk/python/botmanifold
```

## License

Proprietary - see LICENSE file.
