Metadata-Version: 2.4
Name: oriora
Version: 0.1.0
Summary: Python client for Oriora — model selection (decision-only) + OpenAI-compatible routing (Managed API BYOK).
Project-URL: Homepage, https://orioralabs.com
Author: Orioralabs OÜ
License: MIT
Keywords: ai,byok,llm,model-routing,openai,router
Requires-Python: >=3.9
Requires-Dist: requests>=2.25
Description-Content-Type: text/markdown

# Oriora Python SDK

Thin Python client for [Oriora](https://orioralabs.com) — **Managed API BYOK**.

Two ways to use it:

- **`model_select()` — decision only.** Oriora tells you the best model for a task; **you** run the call yourself with your own vendor key. Oriora never sees your key, prompt, or output. Flat **$0.001 per decision**.
- **`chat()` — OpenAI-compatible.** Oriora routes *and* executes the call server-side using the BYOK vendor key you configured, and returns an OpenAI-shaped response.

## Install

```bash
pip install oriora
```

## Authenticate

Generate an `sk_oriora_` API key in your Oriora account → Settings. Pass it directly or set `ORIORA_API_KEY`.

```python
from oriora import Oriora

client = Oriora(api_key="sk_oriora_...")   # or: Oriora()  with ORIORA_API_KEY set
```

## `model_select()` — decision only (you run the call)

```python
rec = client.model_select(task_type="coding")
# {'model': 'anthropic/claude-sonnet-4.6', 'alternatives': [...], 'task_type': 'coding'}

# Then call that model yourself, with your own vendor key:
import anthropic
anthropic.Anthropic().messages.create(model="claude-sonnet-4.6", messages=[...])
```

Restrict the recommendation to your own candidate list (your quality order is kept):

```python
client.model_select(task_type="coding", models=["openai/gpt-5", "anthropic/claude-sonnet-4.6"])
```

Discover the valid task types:

```python
client.task_types()
# ['agentic', 'coding', 'general', 'math', 'reasoning', ...]
```

## `chat()` — OpenAI-compatible (we run the call via your BYOK key)

First, in your Oriora account, store your vendor key and enable BYOK for an **app label** (e.g. `my-app`). Then:

```python
resp = client.chat(
    app="my-app",                # the BYOK app label you enabled
    messages=[{"role": "user", "content": "Explain merge sort in one line."}],
    # model defaults to "oriora-auto" — Oriora picks the best model for your prompt
)
print(resp["choices"][0]["message"]["content"])
```

The response is an OpenAI-shaped `ChatCompletion` dict (`id`, `choices`, `usage`, …), so existing OpenAI-style code works with minimal changes.

> **Note:** `usage` token counts on `chat()` are currently estimated. Specific-model pinning and streaming are not yet supported (use `model="oriora-auto"`).

## Errors

Non-2xx responses raise `OrioraError` (with `.status_code` and `.message`).

```python
from oriora import OrioraError
try:
    client.model_select(task_type="coding")
except OrioraError as e:
    print(e.status_code, e.message)
```

## Pricing

- `model_select()` — flat **$0.001 / decision**.
- `chat()` — Managed API BYOK orchestration fee on the call (your vendor bills you directly for the AI usage on your own key).
