Metadata-Version: 2.4
Name: lushai
Version: 0.1.0
Summary: Official Python SDK for the LushAI Chat API — a Mizo-first AI assistant you can shape with your own system prompt.
Project-URL: Homepage, https://chat.lushaitech.com
Project-URL: Documentation, https://chat.lushaitech.com/developers
Author-email: LushAI Technologies <lushaitechnologies@gmail.com>
License: MIT
Keywords: ai,chat,llm,lushai,mizo,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
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 :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# lushai

Official Python SDK for the [LushAI Chat API](https://chat.lushaitech.com/developers).

Bring your own system prompt and the assistant becomes your product — your name, your persona, your language. Mizo-first by default, but the language is yours to choose.

```bash
pip install lushai
```

Requires Python 3.9+.

## Quickstart

```python
from lushai import LushAI

client = LushAI()  # reads LUSHAI_API_KEY from the environment

res = client.chat.create(message="Chibai! I dam em?")
print(res.reply)
```

## Your assistant, your prompt

A `system_prompt` decides the assistant's name, persona, tone, scope, and reply language:

```python
res = client.chat.create(
    message="Refund status for order 123?",
    system_prompt="You are Acme's support bot. Be terse and formal. Reply in English.",
)
```

**The API ships unnamed.** If your prompt gives no name, the assistant has none — it will not invent one, will not call itself LushAI, and will not name a creator. If your prompt sets no language, it replies in the language the user wrote in.

Omit `system_prompt` entirely and you get the default LushAI Chat persona: a Mizo-first assistant.

You can also set a default prompt per key in the admin dashboard. Resolution order:

1. The request's `system_prompt`
2. The key's stored default prompt
3. None — the default LushAI persona

Passing `system_prompt=""` explicitly opts out of the stored default for that one request.

## Streaming

`chat.stream()` yields text chunks as they arrive:

```python
for chunk in client.chat.stream(message="Chibai!"):
    print(chunk, end="", flush=True)
```

Breaking out of the loop early stops generation server-side.

## Async

Every method has an async twin on `AsyncLushAI`:

```python
import asyncio
from lushai import AsyncLushAI

async def main():
    async with AsyncLushAI() as client:
        res = await client.chat.create(message="Chibai!")
        print(res.reply)

        async for chunk in client.chat.stream(message="Tell me more"):
            print(chunk, end="", flush=True)

asyncio.run(main())
```

## Conversations

LushAI stores conversation history for you — you don't resend previous turns. Omit `conversation_id` to start a thread, then pass the returned id to continue it:

```python
first = client.chat.create(message="My name is Alice.")

second = client.chat.create(
    message="What's my name?",
    conversation_id=first.conversation_id,
)
```

Conversations are scoped to the key that created them.

## Errors

Every failure is a typed exception. Branch on the class or on `.code` — never on the message, which may change.

```python
from lushai import RateLimitError, ValidationError, AuthenticationError

try:
    client.chat.create(message="hi")
except RateLimitError as err:
    print(f"Quota exhausted. Retry in {err.retry_after}s.")
except ValidationError as err:
    print(f"Bad request: {err.message}")
except AuthenticationError:
    print("Check your API key.")
```

| Class | Status | Meaning |
| --- | --- | --- |
| `ValidationError` | 400, 413 | Malformed body or a field failed validation |
| `AuthenticationError` | 401 | Missing, invalid, or revoked API key |
| `PermissionError` | 403 | Key lacks a permission, or the conversation belongs to another key |
| `NotFoundError` | 404 | No such resource |
| `RateLimitError` | 429 | Daily quota exhausted — see `.retry_after` |
| `ServiceUnavailableError` | 5xx | Upstream failure — safe to retry |
| `ConnectionError` | — | Network failure or timeout; no response received |

All inherit from `LushAIError`, and every one carries `.request_id` — quote it when reporting a problem.

## Rate limits

Each key has a daily request quota that resets at 00:00 UTC. After any request, read the current standing:

```python
client.chat.create(message="hi")
print(client.rate_limit)
# RateLimitInfo(limit=1000, remaining=987, reset=1753920000)
```

The SDK retries `429` and `5xx` automatically with exponential backoff (2 attempts by default), honouring `Retry-After`. Validation errors are never retried.

## Configuration

```python
client = LushAI(
    api_key="...",     # default: os.environ["LUSHAI_API_KEY"]
    timeout=600.0,     # per-request seconds, default 10 minutes
    max_retries=2,     # default 2; 0 disables
)
```

Both clients are context managers, which close the underlying connection pool:

```python
with LushAI() as client:
    ...
```

To share a connection pool or add instrumentation, pass your own `httpx` client:

```python
import httpx
client = LushAI(http_client=httpx.Client(proxy="http://localhost:8080"))
```

## Security

**Call this API from your backend only.** An API key carries your full quota and cannot be scoped to a browser origin. Never ship one in client-side code or a public repository.

## API reference

Full endpoint documentation, including the raw HTTP interface: [chat.lushaitech.com/developers](https://chat.lushaitech.com/developers)

## License

MIT
