Metadata-Version: 2.4
Name: lamina-sdk
Version: 0.3.0
Summary: Async-first Python SDK for Lamina video generation.
Author: Lamina
License: MIT
Project-URL: Homepage, https://laminalabs.ai
Project-URL: Source, https://github.com/LaminaLabs/lamina
Project-URL: Issues, https://github.com/LaminaLabs/lamina/issues
Keywords: lamina,simi,video,video-generation,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT 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: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.27.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Dynamic: license-file

# lamina-sdk

Async-first Python SDK for Lamina video generation. Duration values are whole minutes, from 1 to 5.

## Install

```bash
pip install lamina-sdk
```

Python 3.11 or newer is required.

## Quick Start

```python
from lamina import Simi

async with Simi(api_key="lamina_your_key") as client:
    video = await client.generate("A blue sphere moving across white background", duration=1)
    await video.save("out.mp4")
```

You can also set `LAMINA_API_KEY` and call `Simi()` with no arguments. Requests go to
`https://api.laminalabs.ai` unless you set `base_url=...`.

## Submit And Stream Events

```python
from lamina import Simi

async with Simi(api_key="lamina_your_key") as client:
    job = await client.submit_async(
        "A blue sphere moving across white background",
        duration=1,
        document="brief.txt",
    )

    async for event in client.stream_events(job):
        if event.is_progress():
            print(event.payload["phase"], event.payload.get("progress"))
        else:
            print(event.type)
```

Events use a small public vocabulary: `progress`, `chunk`, `output`, `job.completed`,
`job.failed`, and `job.cancelled`. If the stream drops, the SDK reconnects and resumes
from the last sequence it delivered, so you will not see an event twice.

## Callback Style

```python
from lamina import Simi

async with Simi(api_key="lamina_your_key") as client:
    job = await client.submit_async("A narrated lesson about derivatives")
    job.onstream(lambda event: print(event.type))
    job.oncompletion(lambda video: print(f"Ready: {video.job_id}"))
    await job.wait()
```

## Listing And Cancelling

```python
async with Simi() as client:
    jobs = await client.list_jobs(limit=10, status="complete")
    for job in jobs:
        print(job.job_id, job.status)

    await client.cancel("job_abc123")
```

## Retries And Errors

Reads are retried automatically on 429 and 5xx with exponential backoff, honouring
`retry-after`. A submit is only retried when you pass an `idempotency_key`, so a retry can
never create a second video.

```python
from lamina import Simi, SimiRateLimitError

async with Simi(max_retries=3) as client:
    try:
        job = await client.submit_async("Explain our refund policy", idempotency_key="req-1")
    except SimiRateLimitError as error:
        print(error.status, error.retry_after, error.request_id)
```

Errors all derive from `SimiError`: `SimiAPIError` (with `status`, `request_id`, and
`retry_after`), `SimiRateLimitError`, `SimiJobError`, `SimiStreamError`,
`SimiDownloadError`, and `SimiCancelledError`.

## Public API

- `job = client.submit(prompt, *, duration=1, document=None, language=None, idempotency_key=None)`
- `job = await client.submit_async(...)` — same arguments
- `video = await client.generate(...)` — same arguments, waits for completion
- `jobs = await client.list_jobs(*, limit=20, cursor=None, status=None)`
- `state = await client.cancel(job_or_id)`
- `playback = await client.get_playback(job_or_video_or_id)`
- `await client.save(job_or_video, path)`
- `await client.aclose()` or `async with Simi()`
- `api_key` is required in `Simi(...)` unless `LAMINA_API_KEY` is set.
- `duration` is in minutes (1-5).

Use `async with` in async code. `with` is supported only outside a running event loop and
will tell you so if you get it wrong.
