Metadata-Version: 2.4
Name: marona
Version: 0.2.15
Summary: Official Python client SDK for Marona-compatible AI runtimes and Hub integrations.
Author: Blessing Nyuwani
License-Expression: MIT
Project-URL: Homepage, https://www.marona.ai
Project-URL: Repository, https://github.com/BlessingNyuwani/edge-node-service
Project-URL: Documentation, https://hub.marona.ai
Keywords: marona,sdk,mcp,agents,ai,runtime
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1.0,>=0.28
Provides-Extra: dev
Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
Requires-Dist: build<2.0,>=1.2; extra == "dev"
Requires-Dist: twine<7.0,>=6.0; extra == "dev"
Dynamic: license-file

# marona

Official Python client for Marona-compatible AI runtimes and Hub integrations.

Use `marona` to build web apps, mobile backends, WhatsApp bots, desktop apps,
devices, smart glasses, and agents that need one API for online, offline, and
hybrid AI execution.

## Install

```bash
pip install marona
```

## Complete Example

This example shows the normal flow for a developer application:

1. Create a Marona client.
2. Sync Hub metadata into the local cache.
3. Connect approved Hub apps by app ID.
4. Send a user message through the runtime.
5. Print the final assistant response.

The optional `developer` role controls app behavior for that request, such as
tone or response style. It does not configure the model endpoint, model
settings, tools, or user identity.

```python
import asyncio
import os

from marona import Marona


async def main() -> None:
    api_key = os.environ["MARONA_API_KEY"]
    identity_token = os.getenv("MARONA_IDENTITY_TOKEN")  # Optional

    async with Marona(api_key=api_key, mode="online") as marona:
        await marona.sync(
            interface="api",
            identity_token=identity_token,
        )

        tools = await marona.hub.connect(
            ["sda-books", "zimsec"],
            adapter="tools",
        )

        response = await marona.client(
            input=[
                {
                    "role": "developer",
                    "content": "Keep answers clear and concise.",
                },
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "input_text",
                            "text": "What teams are playing in this image?",
                        },
                        {
                            "type": "input_image",
                            "image_url": "https://api.nga.gov/iiif/a2e6da57-3cd1-4235-b20e-95dcaefed6c8/full/!800,800/0/default.jpg",
                        },
                        {
                            "type": "input_file",
                            "filename": "document.pdf",
                            "file_data": "data:application/pdf;base64,...",
                            "detail": "high",
                        },
                    ],
                }
            ],
            interface="api",
            identity_token=identity_token,
            tools=tools,
        )

        print(response.text)


asyncio.run(main())
```

Run it:

```bash
export MARONA_API_KEY="mrn_live_..."
python app.py
```

## Pair A User

Use pairing when an interface needs to become the same user across web, mobile,
WhatsApp, wearables, or another client surface.

```python
async with Marona(api_key=os.environ["MARONA_API_KEY"]) as marona:
    pairing = await marona.start_pairing(
        interface="web",
        device_name="Customer web chat",
    )

    print(pairing.display_code)
    print(pairing.whatsapp_url)

    status = await marona.pairing_status(pairing.pairing_id)
    print(status.status)
```

After the user confirms pairing, store the returned identity token and pass it
to `marona.client(...)`.

## Online, Offline, And Hybrid Modes

Choose one runtime mode for the client:

- `online`: use online runtime and online app routes.
- `offline`: use only local cache, local/private models, and installed offline-capable app targets.
- `hybrid`: try local/private execution first, then use online runtime when allowed.

Apps also declare one availability mode:

- `online`: online only.
- `offline`: offline only.
- `hybrid`: online and offline capable.

Hybrid is a single mode. Do not declare `online + offline + hybrid`; declare
`hybrid`.

## Hybrid Or Offline With A Local/Private Model

Register a local or private model endpoint once, then use it as the default for
hybrid or offline execution.

```python
async with Marona(api_key=os.environ["MARONA_API_KEY"], mode="hybrid") as marona:
    await marona.sync(interface="api")

    marona.models.register(
        name="office-model",
        endpoint="http://localhost:9379",
    )
    marona.models.use("office-model")

    tools = await marona.hub.connect(["sda-books", "zimsec"], adapter="tools")

    response = await marona.client(
        input=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "input_text",
                        "text": "Summarize the chapter about faith.",
                    }
                ],
            }
        ],
        interface="desktop",
        tools=tools,
    )

    print(response.text)
```

In `offline` mode, Marona never calls public cloud runtime. If a model or an
offline-capable app target is missing, the client returns a clear offline error.

## Interface Names

`interface` identifies the client surface making the request. Standard values:

- `api`
- `web`
- `mobile_app`
- `desktop`
- `whatsapp`

Future devices can use custom lowercase slugs such as `smart_glasses`,
`vehicle_console`, or `kiosk`.

## Related Packages

- Python client: `marona`, import `marona`
- Dart client: `marona`, import `package:marona/marona.dart`
- TypeScript client: `marona`, import `Marona` from `"marona"`
- Developer SDK for building apps: `marona-sdk`, import `marona_sdk`
