Metadata-Version: 2.4
Name: locomotiv-sdk
Version: 0.1.0
Summary: Python SDK for authenticated Locomotiv task discovery, run submission, artifacts, and bridge workflows.
Author: Locomotiv
License-Expression: MIT
Project-URL: Homepage, https://github.com/datafre8-company/locomotiv-sdk
Project-URL: Repository, https://github.com/datafre8-company/locomotiv-sdk
Project-URL: Issues, https://github.com/datafre8-company/locomotiv-sdk/issues
Keywords: locomotiv,sdk,pointcloud,mesh,geometry,terrain,geospatial
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Locomotiv Python SDK

The Locomotiv Python SDK is a public client for authenticated task discovery, run submission, artifact inspection, and bridge-session handoff on a Locomotiv-compatible backend.

## Install

Install from PyPI:

```bash
pip install locomotiv-sdk
```

For local development:

```bash
python -m venv .venv
source .venv/bin/activate
pip install -e .
```

## Configure

Set your backend URL and API key:

```bash
export LOCOMOTIV_BASE_URL="https://api.example.com"
export LOCOMOTIV_API_KEY="replace-with-your-api-key"
export LOCOMOTIV_WORKSPACE_ID="replace-with-your-workspace-id"
```

`LOCOMOTIV_WORKSPACE_ID` is optional. When present, `Locomotiv.from_env()` stores it as the active workspace for workspace-scoped helpers and run submission.

## Quickstart

Create a client:

```python
from locomotiv_sdk import Locomotiv

loco = Locomotiv.from_env()
```

Check connectivity and inspect your available tasks:

```python
profile = loco.check_connection()
tasks = loco.tasks.list()
print("Connected as:", profile.get("email") or profile.get("username"))
print("Visible tasks:", len(tasks))
```

Submit a simple run:

```python
from pathlib import Path

run = loco.run(
    task="v1.loco3d.metrics.geometry.aabb",
    input=Path("data/scan.ply"),
    publish=True,
)

final_run = loco.runs.wait(run.id, raise_on_failure=False)
print("Final status:", final_run.status)
```

Inspect the final run and list produced artifacts:

```python
run_detail = loco.run_detail(final_run.id)
artifacts = loco.artifacts.from_run_detail(run_detail)

for artifact in artifacts:
    print(artifact.artifact_id, artifact.type, artifact.download_path)
```

## Task and Run Input Modes

The SDK supports three distinct run-input modes:

- `input` for common single-input or pair-input submission
- `inputs` for explicit keyed-input payloads
- `input_ref` for backend contracts that require a top-level typed saved-object identity

See [docs/run_contracts.md](docs/run_contracts.md) for concrete payload examples and run-contract guidance.

## Downloading Artifacts Safely

Published runs may expose downloadable artifacts through a backend `downloadPath`. Resolve that path through the SDK rather than constructing storage URLs manually:

```python
payload = loco.transport.request("GET", f"/api/v1/runs/{final_run.id}")
artifacts = (payload.get("artifacts") or {}).get("produced") or []
download_path = artifacts[0]["downloadPath"]

signed = loco.artifacts.get_download_link(download_path)
print("Artifact download link resolved.")
print("Expires in:", signed.get("expires_in"))
```

Signed artifact URLs are temporary bearer-style credentials. Treat them as sensitive:

- do not log them
- do not commit them
- do not store them permanently
- do not display them in user-facing UI
- resolve them only when needed
- use them immediately

More detail is available in [docs/artifacts.md](docs/artifacts.md).

## Bridge Sessions

The SDK can create and resolve authenticated bridge sessions for viewer or handoff workflows:

```python
session = loco.bridge.open_user_file(1661, workspace_id="ws_123")
resolved = loco.bridge.resolve(session.id)

print("Launch route:", session.launch_url)
print("Resolved target:", resolved.launch_url)
```

The SDK preserves backend-provided bridge metadata. It does not open browsers or construct frontend routes on its own.

## Examples

Public examples live under [examples/](examples/):

- `connection_and_profile.py`
- `submit_and_wait.py`
- `pair_metric_run.py`
- `explicit_file_and_run.py`

The `examples/smoke_v1/` directory is local-development-oriented reference material for backend contract checks. It is not the recommended first path for public users and is excluded from the clean public staging tree in this release-preparation pass.

## Notes

- Task visibility is controlled by the authenticated backend response. The SDK does not synthesize hidden or non-entitled task catalogs.
- `publish=True` is the expected path when you want downloadable result artifacts.
- Top-level imports are intentionally minimal for this release. Use `from locomotiv_sdk import Locomotiv` for the public entry point, and import specialized helpers from their submodules directly when needed.
