Metadata-Version: 2.4
Name: danube
Version: 0.2.0
Summary: Official Python SDK for Danube
Project-URL: Homepage, https://danubeai.com
Project-URL: Documentation, https://docs.danubeai.com/sdk/python
Author-email: Danube <support@danubeai.com>
License: MIT License
        
        Copyright (c) 2026 Danube AI, Inc.
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: ai,api,danube,mcp,sdk,tools
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
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: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: httpx>=0.25.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: black>=23.0.0; extra == 'dev'
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: respx>=0.20.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# Danube Python SDK

Official Python SDK for [Danube AI](https://danubeai.com) - access services, tools, skills, and user identity through a clean, Pythonic interface.

## Installation

```bash
pip install danube
```

Or install from source:

```bash
pip install -e .
```

## Quick Start

```python
from danube import DanubeClient

# Initialize with API key (or set DANUBE_API_KEY environment variable)
client = DanubeClient(api_key="dk_...")

# List available services
services = client.services.list(limit=5)
for service in services:
    print(f"{service.name}: {service.tool_count} tools")

# Search for tools
tools = client.tools.search("send email")
for tool in tools:
    print(f"{tool.name}: {tool.description}")

# Execute a tool
result = client.tools.execute(
    tool_name="Gmail - Send Email",
    parameters={
        "to": "user@example.com",
        "subject": "Hello from Danube!",
        "body": "This email was sent using the Danube SDK."
    }
)

if result.success:
    print(f"Success: {result.content}")
else:
    print(f"Error: {result.error}")

# Clean up
client.close()
```

## Usage

### Context Manager (Recommended)

```python
from danube import DanubeClient

with DanubeClient(api_key="dk_...") as client:
    services = client.services.list()
    # Client automatically closes when exiting the context
```

### Async Usage

For better performance in async applications:

```python
import asyncio
from danube import AsyncDanubeClient

async def main():
    async with AsyncDanubeClient(api_key="dk_...") as client:
        # Parallel requests
        services, tools = await asyncio.gather(
            client.services.list(limit=10),
            client.tools.search("weather"),
        )

        # Execute a tool
        result = await client.tools.execute(
            tool_name="Weather - Get Current",
            parameters={"city": "San Francisco"}
        )
        print(result.content)

asyncio.run(main())
```

## API Reference

### Services

```python
# List/search services
services = client.services.list(query="github", limit=10)

# Get a specific service
service = client.services.get("service-uuid")

# Get tools for a service
result = client.services.get_tools("service-uuid")
if result.needs_configuration:
    print(f"Configure at: {result.configuration_url}")
else:
    for tool in result.tools:
        print(tool.name)
```

### Tools

```python
# Search for tools
tools = client.tools.search("send email", service_id="optional-filter")

# Get a specific tool
tool = client.tools.get("tool-uuid")

# Execute by ID (faster)
result = client.tools.execute(tool_id="tool-uuid", parameters={"key": "value"})

# Execute by name (searches first)
result = client.tools.execute(tool_name="Gmail - Send Email", parameters={...})

# Check result
if result.success:
    print(result.content)
    print(f"Took {result.duration_ms}ms")
else:
    print(f"Error: {result.error}")
```

### Skills

```python
# Search for skills
skills = client.skills.search("pdf processing")

# Get full skill content
skill = client.skills.get(skill_id="skill-uuid")
# or
skill = client.skills.get(skill_name="pdf-processing")

print(f"Instructions:\n{skill.skill_md}")

for script in skill.scripts:
    print(f"Script: {script.name}")
    print(script.content)
```

### Identity

```python
# Get user identity
identity = client.identity.get()
print(f"Name: {identity.name}")
print(f"Email: {identity.email}")

# Search contacts
contacts = client.identity.search_contacts("john", limit=5)
for contact in contacts:
    print(f"{contact.name} ({contact.email})")
```

## Configuration

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `DANUBE_API_KEY` | Your Danube API key | (required) |
| `DANUBE_API_URL` | API base URL | `https://api.danubeai.com` |
| `DANUBE_TIMEOUT` | Request timeout (seconds) | `30` |
| `DANUBE_MAX_RETRIES` | Max retry attempts | `3` |

### Programmatic Configuration

```python
from danube import DanubeClient

client = DanubeClient(
    api_key="dk_...",
    base_url="https://api.danubeai.com",
    timeout=60.0,
    max_retries=5,
)
```

## Error Handling

```python
from danube import DanubeClient
from danube.exceptions import (
    NotFoundError,
    ExecutionError,
    ConfigurationRequiredError,
    RateLimitError,
    AuthenticationError,
)

with DanubeClient() as client:
    try:
        result = client.tools.execute(tool_id="invalid-id")
    except AuthenticationError:
        print("Invalid API key")
    except NotFoundError as e:
        print(f"Tool not found: {e}")
    except ExecutionError as e:
        print(f"Execution failed: {e}")
    except ConfigurationRequiredError as e:
        print(f"Configure credentials at: {e.configuration_url}")
    except RateLimitError as e:
        if e.retry_after:
            print(f"Rate limited. Retry in {e.retry_after}s")
```

## Models

### Service

| Field | Type | Description |
|-------|------|-------------|
| `id` | str | Service UUID |
| `name` | str | Service name |
| `description` | str | Service description |
| `service_type` | str | "mcp_server", "api", or "internal" |
| `tool_count` | int | Number of available tools |
| `is_connected` | bool | Whether MCP service is connected |

### Tool

| Field | Type | Description |
|-------|------|-------------|
| `id` | str | Tool UUID |
| `name` | str | Tool name |
| `description` | str | Tool description |
| `service_id` | str | Parent service ID |
| `parameters` | dict | Parameter definitions |

### ToolResult

| Field | Type | Description |
|-------|------|-------------|
| `success` | bool | Whether execution succeeded |
| `result` | Any | Execution result |
| `error` | str | Error message (if failed) |
| `content` | str | Result as text (property) |
| `duration_ms` | float | Execution time |

### Skill / SkillContent

| Field | Type | Description |
|-------|------|-------------|
| `id` | str | Skill UUID |
| `name` | str | Skill name |
| `description` | str | Skill description |
| `skill_md` | str | Main SKILL.md content |
| `scripts` | list | Script files |
| `references` | list | Reference files |
| `assets` | list | Asset files |

### Identity / Contact

| Field | Type | Description |
|-------|------|-------------|
| `profile` | dict | User profile data |
| `key_people` | list | Important contacts |
| `contacts` | list | General contacts |
| `name` | str | Contact name |
| `email` | str | Contact email |

## Development

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

# Run tests
pytest

# Type checking
mypy src/danube

# Format code
black src/danube tests
ruff check src/danube tests
```

## License

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