# Contiss Python SDK

Official Python SDK for [Contiss AI](https://contiss.ai) - Unlimited Memory for AI Agents

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

## Features

- 🚀 **Modern Python** - Built for Python 3.8+ with full type hints
- 🔒 **Type Safe** - Pydantic models for request/response validation
- ⚡ **Async Support** - Full async/await support with httpx
- 🧪 **Well Tested** - Comprehensive test suite with 90%+ coverage
- 📝 **Great DX** - Intuitive API with excellent documentation
- 🛡️ **Production Ready** - Retry logic, error handling, and timeouts

## Installation

```bash
pip install contiss
```

## Quick Start

```python
from contiss import Contiss

# Initialize with API key
client = Contiss(api_key="sk_live_...")

# Or from environment variable
# export CONTISS_API_KEY="sk_live_..."
client = Contiss()

# Write a memory
memory = client.memory.write(
    org_id="your_org_id",
    project_id="your_project_id",
    content="User prefers dark mode",
    type="fact",
    tags=["ui", "preferences"]
)
print(f"Memory saved: {memory.id}")

# Search memories
results = client.memory.search(
    org_id="your_org_id",
    project_id="your_project_id",
    query="What are the user's UI preferences?",
    limit=10
)

for memory in results.items:
    print(f"Found: {memory.content} (similarity: {memory.similarity:.2f})")

# Clean up
client.close()
```

## Authentication

### Using API Keys

```python
from contiss import Contiss

# Initialize with API key
client = Contiss(api_key="sk_live_...")
```

### Using JWT Tokens

```python
from contiss import Contiss

# Login with email/password
client = Contiss.login(
    email="user@example.com",
    password="your_password"
)

# Or register a new user
client = Contiss.register(
    email="new@example.com",
    password="secure_password",
    org_name="My Company",
    name="John Doe"
)
```

### Managing API Keys

```python
# Create an API key (requires JWT authentication)
client = Contiss.login(email="...", password="...")

api_key = client.auth.create_api_key(
    name="Production Key",
    expires_in_days=90
)
print(f"API Key (save this!): {api_key.key}")
print(f"Expires: {api_key.expires_at}")

# List all API keys
keys = client.auth.list_api_keys()
for key in keys.keys:
    print(f"{key.name}: {key.key_prefix} (last used: {key.last_used_at})")

# Delete an API key
client.auth.delete_api_key(key_id="key_uuid")
```

## Memory Operations

### Write Memory

```python
# Simple write
memory = client.memory.write(
    org_id="org_uuid",
    project_id="proj_uuid",
    content="User's favorite color is blue"
)

# Write with all options
memory = client.memory.write(
    org_id="org_uuid",
    project_id="proj_uuid",
    content="User decided to use TypeScript for the frontend",
    type="decision",
    title="Frontend Technology Decision",
    tags=["architecture", "frontend"],
    confidence=0.95,
    requires_review=False
)

# Update existing memory (versioning)
updated = client.memory.write(
    org_id="org_uuid",
    project_id="proj_uuid",
    content="User decided to use React with TypeScript",
    supersedes_id=memory.id  # Creates version 2
)
```

### Search Memories

```python
# Semantic search (default: hybrid)
results = client.memory.search(
    org_id="org_uuid",
    project_id="proj_uuid",
    query="What technology choices were made?",
    limit=10
)

# Search with filters
results = client.memory.search(
    org_id="org_uuid",
    project_id="proj_uuid",
    query="user preferences",
    types=["fact", "preference"],
    tags=["ui"],
    search_mode="semantic",
    limit=5
)

# Process results
for memory in results.items:
    print(f"{memory.type}: {memory.content}")
    if memory.similarity:
        print(f"  Relevance: {memory.similarity:.2%}")
```

### Get Memory Bundle

```python
# Get contextual bundle for a task
bundle = client.memory.bundle(
    org_id="org_uuid",
    project_id="proj_uuid",
    task="Build user profile page",
    max_items=12,
    max_chars=6000
)

print(f"Summary: {bundle.summary}")
print(f"Memories: {bundle.total_items}")
for memory in bundle.items:
    print(f"  - {memory.content}")
```

## Context Manager Support

Use the client as a context manager for automatic cleanup:

```python
from contiss import Contiss

with Contiss(api_key="sk_live_...") as client:
    memory = client.memory.write(
        org_id="org_uuid",
        project_id="proj_uuid",
        content="Example memory"
    )
    print(f"Memory saved: {memory.id}")
# Client automatically closed
```

## Error Handling

```python
from contiss import Contiss, ContissError, AuthenticationError, NotFoundError

client = Contiss(api_key="sk_live_...")

try:
    memory = client.memory.write(
        org_id="org_uuid",
        project_id="proj_uuid",
        content="Test memory"
    )
except AuthenticationError:
    print("Authentication failed! Check your API key.")
except NotFoundError:
    print("Project not found or access denied.")
except ContissError as e:
    print(f"API error: {e.message}")
finally:
    client.close()
```

## Configuration

### Environment Variables

```bash
# API Key
export CONTISS_API_KEY="sk_live_..."

# Custom API URL (for development)
export CONTISS_API_URL="http://localhost:8080"
```

### Custom Configuration

```python
client = Contiss(
    api_key="sk_live_...",
    base_url="https://api.contiss.ai",  # Custom API URL
    timeout=60.0,                        # Request timeout (seconds)
    max_retries=3                        # Max retry attempts
)
```

## Advanced Usage

### Memory Types

Choose the appropriate memory type for better organization:

```python
# Facts - Objective information
client.memory.write(
    content="User's email is john@example.com",
    type="fact"
)

# Decisions - Important choices
client.memory.write(
    content="Decided to use PostgreSQL for database",
    type="decision"
)

# Plans - Future intentions
client.memory.write(
    content="Plan to migrate to microservices architecture",
    type="plan"
)

# Summaries - Condensed information
client.memory.write(
    content="User prefers dark mode and large fonts",
    type="summary"
)

# Notes - General observations
client.memory.write(
    content="User asked about pricing page",
    type="note"
)
```

### Search Modes

```python
# Semantic search - Best for meaning-based queries
results = client.memory.search(
    query="dark theme settings",
    search_mode="semantic"
)

# Full-text search - Best for exact keyword matching
results = client.memory.search(
    query="dark mode",
    search_mode="fulltext"
)

# Hybrid search - Combines both (recommended)
results = client.memory.search(
    query="user interface preferences",
    search_mode="hybrid"  # Default
)
```

### Versioning

Track changes to memories over time:

```python
# Create initial memory
v1 = client.memory.write(
    content="User likes Python",
    type="fact"
)

# Update with new information
v2 = client.memory.write(
    content="User prefers Python over JavaScript",
    supersedes_id=v1.id  # Links to v1
)

print(f"Version 1: {v1.id}")
print(f"Version 2: {v2.id} (version {v2.version})")
```

## Type Hints

The SDK has full type hint support:

```python
from contiss import Contiss, Memory, SearchResult, MemoryWriteResult

client: Contiss = Contiss(api_key="sk_live_...")

# Type-checked operations
memory: MemoryWriteResult = client.memory.write(...)
results: SearchResult = client.memory.search(...)

# Access typed fields
for item: Memory in results.items:
    content: str = item.content
    similarity: float = item.similarity or 0.0
```

## Development

### Setup

```bash
# Clone repository
git clone https://github.com/devotel/contiss-python.git
cd contiss-python

# Install dependencies
pip install -e ".[dev]"
```

### Run Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=contiss --cov-report=html

# Run specific test file
pytest tests/test_memory.py
```

### Code Quality

```bash
# Type checking
mypy contiss

# Linting
ruff check contiss

# Formatting
black contiss tests
isort contiss tests
```

## API Reference

### Contiss Client

```python
client = Contiss(
    api_key: Optional[str] = None,
    token: Optional[str] = None,
    base_url: str = "https://api.contiss.ai",
    timeout: float = 30.0,
    max_retries: int = 3
)
```

**Class Methods:**
- `Contiss.login(email, password)` - Login and get JWT token
- `Contiss.register(email, password, org_name, name=None)` - Register new user

**Instance Methods:**
- `client.health()` - Check API health
- `client.close()` - Close HTTP client

**Resources:**
- `client.memory` - Memory operations
- `client.auth` - Authentication operations

### Memory Resource

```python
client.memory.write(
    org_id: str,
    project_id: str,
    content: str,
    type: MemoryType = "note",
    title: Optional[str] = None,
    tags: Optional[List[str]] = None,
    sources: Optional[List[str]] = None,
    confidence: float = 0.6,
    requires_review: bool = False,
    supersedes_id: Optional[str] = None
) -> MemoryWriteResult

client.memory.search(
    org_id: str,
    project_id: str,
    query: str,
    limit: int = 20,
    types: Optional[List[MemoryType]] = None,
    tags: Optional[List[str]] = None,
    search_mode: SearchMode = "hybrid"
) -> SearchResult

client.memory.bundle(
    org_id: str,
    project_id: str,
    task: str,
    max_items: int = 12,
    max_chars: int = 6000,
    types: Optional[List[MemoryType]] = None,
    tags: Optional[List[str]] = None
) -> BundleResult
```

### Auth Resource

```python
client.auth.create_api_key(
    name: str,
    expires_in_days: Optional[int] = None
) -> APIKeyCreate

client.auth.list_api_keys() -> APIKeyList

client.auth.delete_api_key(key_id: str) -> bool
```

## Support

- **Documentation**: [docs.contiss.ai](https://docs.contiss.ai)
- **Issues**: [GitHub Issues](https://github.com/devotel/contiss-python/issues)
- **Discord**: [Join our community](https://discord.gg/contiss)
- **Email**: support@contiss.ai

## License

MIT License - see [LICENSE](LICENSE) file for details

## Contributing

Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes
4. Run tests (`pytest`)
5. Commit your changes (`git commit -m 'Add amazing feature'`)
6. Push to the branch (`git push origin feature/amazing-feature`)
7. Open a Pull Request

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for version history.

---

Made with ❤️ by the [Contiss AI](https://contiss.ai) team
