# odins-eye

[![PyPI version](https://badge.fury.io/py/odins-eye.svg)](https://badge.fury.io/py/odins-eye)
[![Python versions](https://img.shields.io/pypi/pyversions/odins-eye.svg)](https://pypi.org/project/odins-eye/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Python client library for the Brookmimir API.

## Features

- **Synchronous and Asynchronous clients** - Choose between sync (`OdinsEyeClient`) or async (`AsyncOdinsEyeClient`) based on your needs
- **Comprehensive API coverage** - Access all Brookmimir API endpoints
- **Type-safe** - Full type hints with Pydantic validation
- **Automatic retries** - Built-in retry logic with exponential backoff
- **Rate limiting handling** - Automatic detection and handling of rate limits
- **HTTP/2 support** - Faster connections with HTTP/2
- **Context manager support** - Automatic resource cleanup
- **Debug logging** - Optional logging for troubleshooting
- **Comprehensive error handling** - Detailed error messages and exception types

## Installation

Install from PyPI:

```bash
pip install odins-eye
```

Install with development dependencies:

```bash
pip install odins-eye[dev]
```

## Quick Start

### Synchronous Usage

```python
from odins_eye import OdinsEyeClient

# Initialize the client
client = OdinsEyeClient(api_key="your-api-key")

try:
    # Check API status
    status = client.index()
    print(f"API Status: {status}")

    # Get user profile
    profile = client.profile()
    print(f"User: {profile['user']['name']}")

    # Check credit balance
    credits = client.credits()
    print(f"Balance: {credits['current_balance']}")
finally:
    client.close()
```

### Asynchronous Usage

```python
import asyncio
from odins_eye import AsyncOdinsEyeClient

async def main():
    async with AsyncOdinsEyeClient(api_key="your-api-key") as client:
        # Make concurrent requests
        status, profile, credits = await asyncio.gather(
            client.index(),
            client.profile(),
            client.credits()
        )
        print(f"API Status: {status}")
        print(f"User: {profile['user']['name']}")
        print(f"Credits: {credits['current_balance']}")

asyncio.run(main())
```

### Using Context Managers (Recommended)

```python
with OdinsEyeClient(api_key="your-api-key") as client:
    status = client.index()
    print(status)

# Async version
async with AsyncOdinsEyeClient(api_key="your-api-key") as client:
    status = await client.index()
    print(status)
```

## API Methods

### Status and Version

```python
# Get API status
status = client.index()

# Get API version
version = client.version()

# Run network test
result = client.nettest()
```

### User Profile and Credits

```python
# Get user profile
profile = client.profile()
print(f"Name: {profile['user']['name']}, Age: {profile['user']['age']}")

# Check credit balance
credits = client.credits()
print(f"Balance: {credits['current_balance']}")
```

### Document Retrieval

```python
# Fetch a document by ID
document = client.document("doc-123")
```

### Query Submission

```python
# Submit a query
query_result = client.query({
    "query": {
        "match_all": {}
    }
})
```

### Face Search

```python
# Basic face search
results = client.face_search("path/to/image.jpg")

# Face search with canonical proxy parameters
results = client.face_search(
    "path/to/image.jpg",
    top_k=10,
    min_score=0.8,
)

# Embedding-based face search
results = client.face_search(
    embedding=[0.5] * 512,
    top_k=5,
)
```

## Error Handling

The client provides detailed error information through exception types:

```python
from odins_eye import OdinsEyeClient, OdinsEyeAPIError, OdinsEyeError

with OdinsEyeClient(api_key="your-api-key") as client:
    try:
        result = client.profile()
    except OdinsEyeAPIError as e:
        # API returned an error (4xx or 5xx)
        print(f"API Error: {e.message}")
        print(f"Status Code: {e.status_code}")
        if e.error:
            print(f"Error: {e.error}")
        if e.error_details:
            print(f"Details: {e.error_details}")
    except OdinsEyeError as e:
        # Client-side error (validation, network, etc.)
        print(f"Client Error: {e.message}")
```

### Handling Rate Limits

Rate limiting is automatically handled with retries:

```python
from odins_eye import OdinsEyeAPIError

try:
    result = client.profile()
except OdinsEyeAPIError as e:
    if e.status_code == 429:
        print("Rate limit exceeded")
        if e.rate_limit_reset:
            print(f"Resets at: {e.rate_limit_reset}")
```

## Configuration

### Custom Timeout

```python
import httpx
from odins_eye import OdinsEyeClient

timeout = httpx.Timeout(30.0, connect=10.0)
client = OdinsEyeClient(api_key="your-api-key", timeout=timeout)
```

### Custom Retry Configuration

```python
from odins_eye import OdinsEyeClient, RetryConfig

retry_config = RetryConfig(
    max_retries=5,
    initial_delay=2.0,
    max_delay=120.0,
    exponential_base=2.0,
    retry_on_rate_limit=True
)

client = OdinsEyeClient(
    api_key="your-api-key",
    retry_config=retry_config
)
```

### Enable Debug Logging

```python
import logging
from odins_eye import OdinsEyeClient

# Configure logging
logging.basicConfig(level=logging.DEBUG)

# Enable client logging
client = OdinsEyeClient(
    api_key="your-api-key",
    enable_logging=True
)
```

### Custom Headers

```python
client = OdinsEyeClient(
    api_key="your-api-key",
    headers={
        "X-Custom-Header": "value"
    }
)
```

## Environment Variables

For security, consider using environment variables for your API key:

```python
import os
from odins_eye import OdinsEyeClient

api_key = os.getenv("BROOK_MIMIR_API_KEY")
client = OdinsEyeClient(api_key=api_key)
```

## Requirements

- Python >= 3.9
- httpx[http2] >= 0.27.0
- pydantic >= 2.6.0

## API Documentation

For detailed API documentation, visit the [Brookmimir API docs](https://brookmimir.com/docs).

## Changelog

See [CHANGELOG.md](https://pypi.org/project/odins-eye/#history) for release history and changes.

## License

This project is licensed under the MIT License - see the LICENSE file for details.

## Links

- **PyPI Package**: <https://pypi.org/project/odins-eye/>
- **Brookmimir**: <https://brookmimir.com>

## Support

For support and questions:

- Contact Brookmimir support at <https://brookmimir.com/support>
- Review the [API documentation](https://brookmimir.com/docs)
