Metadata-Version: 2.4
Name: nevo-sdk
Version: 0.1.0
Summary: Python SDK for Nevo — the inbound event gateway.
Project-URL: Homepage, https://nevo.sh
Project-URL: Documentation, https://docs.nevo.sh/python
Project-URL: Repository, https://github.com/nevo-dev/nevo
Project-URL: Issues, https://github.com/nevo-dev/nevo/issues
Author: Nevo
License: MIT
License-File: LICENSE
Keywords: agents,ai,events,webhooks,websocket
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
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.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx<0.29,>=0.27
Requires-Dist: websockets<14.0,>=12.0
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# Nevo Python Library

[![PyPI version](https://img.shields.io/pypi/v/nevo.svg)](https://pypi.org/project/nevo/)
[![Python versions](https://img.shields.io/pypi/pyversions/nevo.svg)](https://pypi.org/project/nevo/)
[![License](https://img.shields.io/pypi/l/nevo.svg)](https://pypi.org/project/nevo/)

The official Python library for [Nevo](https://nevo.sh).

## Documentation

See the [Python quickstart](https://docs.nevo.sh/python) and the [events reference](https://docs.nevo.sh/events).

## Requirements

- Python 3.10+

## Installation

```sh
pip install nevo-sdk
```

The import path stays `nevo` — only the distribution name carries the `-sdk` suffix:

```python
from nevo import Nevo
```

## Usage

The library needs to be configured with an API key from the Nevo dashboard.

```python
import asyncio
from nevo import Nevo

client = Nevo(token="nvo_live_...")

@client.on_event()
async def handle(event):
    print(event.id, event.type, event.prompt_ready)

asyncio.run(client.run())
```

For scripts, there's a blocking convenience:

```python
client.run_sync()
```

### Events

Every event exposes the following fields:

| Field          | Type                  |                                        |
| -------------- | --------------------- | -------------------------------------- |
| `id`           | `str`                 | stable across replays                  |
| `type`         | `str`                 | `webhook.received` or `email.received` |
| `origin`       | `str`                 | `live` or `replay`                     |
| `created_at`   | `datetime`            |                                        |
| `channel`      | `Channel`             | the channel that received this event   |
| `data`         | `dict`                | the raw source payload                 |
| `webhook`      | `WebhookData \| None` | set when `type == "webhook.received"`  |
| `email`        | `EmailData \| None`   | set when `type == "email.received"`    |
| `prompt_ready` | `str`                 | text rendering of the event            |

Branch on `event.type`:

```python
@client.on_event()
async def handle(event):
    if event.type == "email.received":
        print(event.email.from_, event.email.subject)
    elif event.type == "webhook.received":
        print(event.webhook.method, event.webhook.path)
```

### Configuration

```python
client = Nevo(
    token="nvo_live_...",
    url="wss://api.nevo.sh/v1/stream",
    handler_timeout=30.0,
    reconnect_max_backoff=30.0,
    logger=None,
)
```

| Option                  | Default                       | Description                                  |
| ----------------------- | ----------------------------- | -------------------------------------------- |
| `token`                 | —                             | API key from the Nevo dashboard              |
| `url`                   | `wss://api.nevo.sh/v1/stream` | Override for self-hosted Nevo                |
| `handler_timeout`       | `30.0`                        | Seconds before a handler is considered stuck |
| `reconnect_max_backoff` | `30.0`                        | Cap on exponential reconnect delay           |
| `logger`                | `logging.getLogger("nevo")`   | Your own `logging.Logger`                    |

### Handler behavior

Handlers must be declared with `async def`. Exactly one handler per client — branch on `event.type` inside it.

- If the handler returns, the event is considered handled.
- If the handler raises, the exception is logged and the stream continues.
- If the handler doesn't return before `handler_timeout`, it's logged as a timeout and the stream continues.

Events are not re-delivered to the SDK on handler failure. Replay them from the dashboard when you need to.

### Reconnects

The client reconnects automatically using exponential backoff with jitter, capped at `reconnect_max_backoff`. If the server rejects the API key with a 401, the SDK raises `AuthError` and does not retry.

### Logging

The SDK logs under the `nevo` logger. Enable debug output:

```python
import logging
logging.getLogger("nevo").setLevel(logging.DEBUG)
```

## Errors

All exceptions inherit from `nevo.NevoError`.

| Exception         | Raised when                                         |
| ----------------- | --------------------------------------------------- |
| `AuthError`       | The API key is rejected by the server.              |
| `ConnectionError` | The client cannot connect after exhausting retries. |
| `NevoError`       | Base class.                                         |

```python
from nevo import Nevo, AuthError

try:
    asyncio.run(client.run())
except AuthError:
    # Fix the key and restart.
    ...
```

## Self-hosting

Point `url` at your instance:

```python
Nevo(token="...", url="wss://events.internal/v1/stream")
```

## Support

- Issues: [github.com/nevo-dev/nevo/issues](https://github.com/nevo-dev/nevo/issues)
- Email: [support@nevo.sh](mailto:support@nevo.sh)

## License

MIT
