Metadata-Version: 2.5
Name: dropbear
Version: 0.1.0a4
Summary: Cloud robot policy inference — one function call.
Project-URL: Homepage, https://dropbear.dreamscalelabs.com
Project-URL: Documentation, https://docs.dropbear.dreamscalelabs.com
Author: Dreamscale Labs
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: inference,physical-ai,robotics,vla
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: <3.15,>=3.11
Requires-Dist: dropbear-transport==0.1.1a4
Requires-Dist: httpx<1,>=0.27
Requires-Dist: numpy<3,>=2.0
Requires-Dist: pillow<12,>=10
Requires-Dist: rich<14,>=13.9
Requires-Dist: tomli-w<2,>=1.0
Requires-Dist: typer<0.26,>=0.12
Requires-Dist: typing-extensions<5,>=4.10
Provides-Extra: dreamzero
Requires-Dist: av==15.0.0; extra == 'dreamzero'
Provides-Extra: sim
Requires-Dist: bddl==1.0.1; extra == 'sim'
Requires-Dist: cloudpickle<4,>=2; extra == 'sim'
Requires-Dist: easydict<2,>=1.13; extra == 'sim'
Requires-Dist: future<2,>=1; extra == 'sim'
Requires-Dist: gymnasium<2,>=0.29; extra == 'sim'
Requires-Dist: huggingface-hub<2,>=1; extra == 'sim'
Requires-Dist: imageio<3,>=2.36; extra == 'sim'
Requires-Dist: matplotlib<4,>=3.9; extra == 'sim'
Requires-Dist: mujoco<4,>=3.2; extra == 'sim'
Requires-Dist: opencv-python<5,>=4.10; extra == 'sim'
Requires-Dist: pyyaml<7,>=6; extra == 'sim'
Requires-Dist: robosuite==1.4.1; extra == 'sim'
Requires-Dist: tqdm<5,>=4.66; extra == 'sim'
Provides-Extra: so101
Requires-Dist: lerobot[feetech]==0.5.1; extra == 'so101'
Description-Content-Type: text/markdown

# Dropbear

Cloud robot policy inference — one function call.

> `0.1.0a4` is an unreleased pre-alpha version. The install commands below
> apply after it is published. Repository consumers can build the local
> wheelhouse under `sandbox/consumer-workspaces/` in the meantime.

## Install

Add Dropbear to a Python 3.11–3.14 project:

```bash
uv add "dropbear==0.1.0a4"
```

Install the CLI as a standalone tool:

```bash
uv tool install "dropbear==0.1.0a4"
dropbear login
```

The base package contains cloud inference, transport, model contracts, and
robot-neutral observation helpers. Install a hardware or simulator stack only
when you need it:

```bash
uv add "dropbear[so101]==0.1.0a4"
uv add "dropbear[sim]==0.1.0a4"
uv add "dropbear[dreamzero]==0.1.0a4"
```

The `dreamzero` extra installs the pinned H.264 codec used automatically by
DreamZero-YAM's three persistent camera streams. DreamZero-DROID and all other
models keep their existing JPEG transport and do not require this extra.

The base SDK supports Python 3.11 through 3.14. The `so101` extra currently
supports Python 3.12 and 3.13 because its pinned LeRobot dependency requires
Python 3.12 and does not yet provide a wheel-compatible Python 3.14 dependency
stack.

The `sim` extra is currently Linux/WSL2 only because of upstream
LIBERO/robosuite limitations.

## Cloud policy inference

```python
import dropbear

with dropbear.connect(model="molmoact2-so101") as policy:
    result = policy.predict(
        observation,
        instruction="pick up the cube",
    )

print(len(result.actions), len(result.actions[0]))
```

`predict()` returns one action chunk and does not actuate a robot. Build
`observation` with the model-specific helper and validate every action locally
before adding a motion path.

`dropbear.connect()` is the canonical SDK entrypoint.
`connect_so101()` is a deprecated compatibility path for the legacy physical
SO-101 safety loop and will be removed after that behavior is folded into the
generic policy surface. New cloud-policy work should use `dropbear.connect()`.
There is no first-class public `connect_libero()` or `connect_franka()`
entrypoint; use `dropbear.connect(model="molmoact2-libero")` or select another
checkpoint with `model=`.

Use a context manager so every cloud session closes deterministically:

```python
import dropbear

with dropbear.connect(model="molmoact2-libero") as policy:
    result = policy.run(
        instruction="put the mug on the plate",
        observe=observe,
        act=act,
        max_actions=220,
        strategy=dropbear.RunStrategy.libero_default(),
    )
```

### Action smoothing

`policy.run()` smooths overlapping chunks automatically from the model's action
space without changing the selected control mode or its inference cadence:

```python
strategy = dropbear.RunStrategy()  # action_smoothing="auto"
```

`auto` resolves to `output` for delta-action models such as LIBERO and to
`motion` for absolute-joint models such as SO101. `output` averages old and new
action values at each overlapping logical timestep, using 70% new by default.
`motion` blends consecutive target increments, using 85% new motion by default,
then corrects gradually toward the new absolute targets. Absolute-position
models still receive absolute-position targets; `motion` changes only how
overlapping client trajectories are combined.

For controlled comparisons, set `action_smoothing="output"` or
`action_smoothing="motion"`. `motion` requires an
`absolute_joint_position` contract. Its default correction horizon is
`max(3, ceil(chunk_size / 5))` action steps, so a 30-action SO101 chunk resolves
to six steps. Optional expert overrides are `smoothing_new_weight` and
`smoothing_correction_steps`; the latter applies only to `motion`. These values
resolve once from the static runtime contract and do not adapt to latency.

Returned actions remain aligned to their original logical timesteps. Expired
prefix steps are skipped, and a chunk that is entirely stale is discarded; it
is never shifted forward and replayed. With eager inference, a predicted action
can therefore be superseded or expire without ever being dispatched. This is
intentional: inference stays reactive while the action loop executes only the
currently resolved timestep.

For physical arms that clamp a requested target, return the accepted target so
the next smoothing pass starts from what the robot was actually asked to
execute:

```python
def act(action, context):
    accepted = robot.send_and_return_accepted_target(action)
    return dropbear.ActResult(accepted_action=accepted)
```

`accepted_action` must be finite and have the same dimension as the requested
action. Existing callbacks returning `None`, `bool`, or `ActResult(done=...)`
remain supported.

`policy.run()` returns one `RunResult` and prints the same run-scoped summary
immediately. Its counters and stop condition are deliberately narrow:

- `result.done` means the `act()` callback requested a stop; it does not assert
  task success or completion.
- `result.actions` counts control callback steps, not confirmed physical robot
  execution.
- `result.policy_calls` counts completed policy responses accepted by that run.
- `result.timing.policy_response_ms` measures SDK observation submission through
  action-chunk receipt. It excludes observation construction and physical
  actuation.
- `result.timing.data_plane_rtt_ms` is an authenticated application-path round
  trip measured with a clock probe. It includes transport framing and any
  accelerator or relay hops; it is not a one-way network-latency estimate.
- Worker queue, preprocessing, inference, and postprocessing summaries are
  derived from per-response worker timestamps. Missing samples remain missing
  rather than being inferred from client-side residual time.

`region="nearest"` is the default and pins the lowest measured HTTPS-latency
region, even when another region is already warm. `region="available"` reuses
compatible warm compute in any measured candidate region before starting cold
compute. Passing an AWS region is an exact constraint with no regional fallback.
The latency check uses five serial samples per region and reports when partial
or failed evidence required a deterministic fallback.

`transport="auto"` tries QUIC first and can use the hosted relay;
`transport="quic"` requires QUIC, and `transport="relay"` uses the relay
directly.

## MolmoAct2-DROID on Franka

MolmoAct2-DROID consumes an exterior RGB view and wrist RGB view. A second
exterior view is optional; when omitted, Dropbear reuses the first exterior
frame for the checkpoint's second exterior slot.

Robot state is seven Franka joint positions in radians followed by a gripper
value in `[0, 1]`.

```python
import numpy as np
import dropbear

exterior_rgb = np.zeros((480, 640, 3), dtype=np.uint8)
wrist_rgb = np.zeros((480, 640, 3), dtype=np.uint8)

observation = dropbear.franka.observe(
    exterior_frame=exterior_rgb,
    wrist_frame=wrist_rgb,
    joint_positions=[0.0] * 7,
    gripper=0.5,  # 0=open, 1=closed
)

with dropbear.connect(model="molmoact2-droid") as policy:
    result = policy.predict(
        observation,
        instruction="pick up the green block",
    )

assert len(result.actions) == 15
assert all(len(action) == 8 for action in result.actions)
```

The checkpoint returns a 15-step chunk at 15 Hz. Each action is an absolute
target `[joint_0, ..., joint_6, gripper]`; joints are radians and the gripper is
in `[0, 1]`.

`predict()` does not actuate hardware or provide a Franka safety controller.
Validate joint, velocity, acceleration, workspace, collision, and gripper
limits before sending any target to a robot.

## Manual action loop

For a caller-owned control loop, pass the task instruction to
`policy.next_action(...)`. Dropbear owns inference, refill, action buffering,
calibration, and RTC prefix context; the caller owns sensing, actuation, and
loop cadence.

```python
import time

dt = 1.0 / policy.action_hz
while running:
    tick = time.perf_counter()
    action = policy.next_action(
        observe(),
        instruction="put the mug on the plate",
    )
    robot.execute(action)
    time.sleep(max(0.0, dt - (time.perf_counter() - tick)))
```

## CLI

Sign in once. Credentials are stored in `~/.dropbear/config.toml`.

```bash
dropbear login
dropbear status
```

For headless setup, use bare `--api-key` to paste a key into a hidden prompt:

```bash
dropbear login --api-key
```

Run robot-neutral setup checks:

```bash
dropbear doctor
```

SO-101 and simulation checks are explicit:

```bash
dropbear doctor so101
dropbear doctor sim
```

Install shell completion with:

```bash
dropbear --install-completion
```

Useful session commands:

```bash
dropbear sessions list
dropbear sessions stop <session-id>
dropbear sessions stop --all
```

Documentation: https://docs.dropbear.dreamscalelabs.com
