Metadata-Version: 2.4
Name: alavida-sdk
Version: 0.1.0
Summary: Python SDK for building Alavida platform components
License-Expression: MIT
Requires-Python: >=3.10
Requires-Dist: httpx>=0.24.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
Description-Content-Type: text/markdown

# alavida-sdk

Python SDK for building [Alavida](https://alavida.ai) platform components.

## Install

```bash
pip install alavida-sdk

# With FastAPI helpers:
pip install "alavida-sdk[fastapi]"
```

## Quick Start (FastAPI)

```python
from fastapi import FastAPI, Depends
from alavida_sdk import (
    ComponentSchema, ActionSchema, define_schema,
    complete_job, fail_job, update_progress,
)
from alavida_sdk.fastapi import AlavidaMiddleware, require_auth
from alavida_sdk.types import AuthContext

app = FastAPI()
app.add_middleware(AlavidaMiddleware)  # rejects direct access, allows /health + /schema

# 1. Declare your schema
SCHEMA = ComponentSchema(
    slug="buying-signals",
    name="Buying Signals",
    type="workflow",
    version="1.0.0",
    actions={
        "run": ActionSchema(
            description="Detect buying signals for a list of companies",
            input_schema={
                "type": "object",
                "required": ["companies"],
                "properties": {
                    "companies": {"type": "array", "items": {"type": "object"}},
                },
            },
            output_schema={
                "type": "object",
                "properties": {
                    "companies": {"type": "array"},
                    "summary": {"type": "object"},
                },
            },
        ),
    },
)

@app.get("/health")
async def health():
    return {"status": "ok", "version": "1.0.0"}

@app.get("/schema")
async def schema():
    return define_schema(SCHEMA)

# 2. Handle execution — read auth context from gateway headers
@app.post("/run")
async def run(ctx: AuthContext = Depends(require_auth)):
    input_data = ...  # parse request body

    # Start background processing, return 202
    # When done, call complete_job()
    return {"status": "accepted"}

# 3. After background work finishes:
async def on_complete(callback_url: str, result: dict, credits: int):
    await complete_job(callback_url, result=result, credits_used=credits)

async def on_failure(callback_url: str, error: Exception):
    await fail_job(callback_url, error_code="processing_failed", error_message=str(error))
```

## API Reference

### Core (framework-agnostic)

| Function | Description |
|----------|-------------|
| `get_auth_context(headers)` | Extract `AuthContext` from any headers mapping |
| `define_schema(schema)` | Convert `ComponentSchema` to JSON-serializable dict |
| `complete_job(url, result=, credits_used=)` | Async — notify gateway of successful completion |
| `fail_job(url, error_code=, error_message=)` | Async — notify gateway of failure |
| `update_progress(url, progress=)` | Async — update job progress (0-100) |

### FastAPI Helpers (`alavida_sdk.fastapi`)

| Export | Description |
|--------|-------------|
| `AlavidaMiddleware` | Middleware — rejects requests without gateway headers (skips `/health`, `/schema`) |
| `require_auth` | `Depends()` — injects `AuthContext` into route handlers |

### Types

| Model | Fields |
|-------|--------|
| `ComponentSchema` | `slug`, `name`, `type`, `version`, `actions` |
| `ActionSchema` | `description`, `input_schema`, `output_schema` |
| `AuthContext` | `team_id`, `user_id`, `job_id`, `callback_url?` |

### Exceptions

| Exception | When |
|-----------|------|
| `AlavidaAuthError` | Required `X-Alavida-*` headers are missing |

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `INTERNAL_SECRET` | For callbacks | Shared secret for authenticating callback requests to the gateway |
