Metadata-Version: 2.3
Name: mantis-gw
Version: 1.0.1
Summary: Mantis SDK
Author: Mantis Team
Author-email: Mantis Team <rizwansyed876@gmail.com>
Requires-Dist: httpx
Requires-Python: >=3.13
Description-Content-Type: text/markdown

# Mantis SDK

Python SDK for sending chat completion requests to the Mantis `llm-gateway`
`/v1/chat/completions` endpoint.

## Requirements

- Python 3.13+
- A running `llm-gateway` service
- A gateway API token

## Install

From PyPI:

```bash
pip install mantis_gw
```

From this repo:

```bash
uv sync
```

## Non-streaming

`url` should be the gateway base URL and should not include `/v1/chat/completions`.
The SDK appends that endpoint path automatically.

```python
import asyncio

from mantis_gw import gateway


async def main() -> None:
    client = gateway.Gateway(
        url="https://gateway.example.com",
        token="gw_token-id_token-secret",
    )

    response = await client.send(
        {
            "messages": [
                {"role": "user", "content": "Write a short project summary."},
            ],
            "stream": False,
            "temperature": 0.5,
            "max_tokens": 256,
            "system": "Answer clearly and concisely.",
        },
        metadata={"task-type": "summarization"},
    )

    print(response)


asyncio.run(main())
```

## Streaming

When `stream` is `True`, `send()` returns an async iterator of text chunks.

```python
import asyncio

from mantis_gw import gateway


async def main() -> None:
    client = gateway.Gateway(
        url="https://gateway.example.com",
        token="gw_token-id_token-secret"
    )

    chunks = await client.send(
        {
            "messages": [
                {"role": "user", "content": "Write a short project summary."},
            ],
            "stream": True,
            "temperature": 0.5,
            "max_tokens": 256,
            "system": "Answer clearly and concisely.",
        },
        metadata={"task-type": "summarization"},
    )

    async for chunk in chunks:
        print(chunk, end="")


asyncio.run(main())
```

## Request Payload

The SDK sends the request payload to `llm-gateway` as-is. Gateway-side validation
still applies to the endpoint:

- `messages` is required and must contain at least one message.
- Each message must only contain `role` and `content`.
- `role` must be `"user"` or `"assistant"`.
- `content` must be a non-empty string after trimming whitespace.
- Extra top-level request fields are rejected.
- `stream` defaults to `False`.
- `temperature` can be omitted, `None`, or a number from `0.0` to `2.0`.
- `max_tokens` can be omitted, `None`, or an integer greater than `0`.
- `system` can be omitted, `None`, or a non-empty string after trimming whitespace.

## Metadata

Pass routing metadata with the `metadata` keyword argument. Keys and values must be strings.
The SDK sends it as the gateway's `metadata` HTTP header.

```python
await client.send(
    {
        "messages": [{"role": "user", "content": "Generate a Python function."}],
        "stream": False,
    },
    metadata={"task-type": "code_generation"},
)
```

## Errors

Gateway responses with 4xx or 5xx status codes raise httpx.HTTPStatusError.

## Integration Tests

The integration tests read gateway credentials from a local `.env` file in the
repo root:

```bash
MANTIS_GATEWAY_URL=https://gateway.example.com
MANTIS_GATEWAY_TOKEN=gw_token-id_token-secret
```

Run them with:

```bash
uv run pytest
```

The `.env` file is ignored by Git so real credentials stay local.
