Metadata-Version: 2.4
Name: hestiaos
Version: 1.0.0
Summary: HestiaOS SDK — Domain Interface for the HestiaOS platform
Author: HestiaOS Team
License-Expression: MIT
Project-URL: Homepage, https://hestiaos.local
Project-URL: Documentation, https://hestiaos.github.io/hestiaos
Project-URL: Source, https://github.com/hestiaos/hestiaos
Project-URL: Changelog, https://github.com/hestiaos/hestiaos/blob/main/CHANGELOG.md
Project-URL: Issue Tracker, https://github.com/hestiaos/hestiaos/issues
Keywords: hestiaos,sdk,governance,ai,orchestration
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.27.0
Requires-Dist: typer>=0.12.0
Dynamic: license-file

# 🏠 HestiaOS SDK

**Python SDK for the HestiaOS platform** — deterministic governance, multi-agent orchestration, and local-first AI execution.

[![CI](https://github.com/hestiaos/hestiaos/actions/workflows/sdk.yml/badge.svg)](https://github.com/hestiaos/hestiaos/actions/workflows/sdk.yml)
[![PyPI version](https://img.shields.io/pypi/v/hestiaos)](https://pypi.org/project/hestiaos/)
[![Python Versions](https://img.shields.io/pypi/pyversions/hestiaos)](https://pypi.org/project/hestiaos/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Typed](https://img.shields.io/badge/typed-Yes-green)](https://pypi.org/project/hestiaos/)
[![API Frozen](https://img.shields.io/badge/API-1.0.0--frozen-blue)](CHANGELOG.md)

---

## Installation

```bash
pip install hestiaos
```

Requires Python 3.11+.

---

## Quickstart

### Async (recommended — production)

```python
from hestiaos import AsyncClient

async with AsyncClient(base_url="http://localhost:8000") as client:
    # Single request
    result = await client.run_async("create a report")
    print(result.result)      # "processed: create a report"
    print(result.trace_id)    # "abc-123-def"
    print(result.mode)        # "ALLOW"

    # Streaming
    async for event in client.run_stream("create a report"):
        print(f"[{event.type}] {event.data}")
```

### Sync (CLI / scripts)

```python
from hestiaos import Client

client = Client(base_url="http://localhost:8000")

# Single request
result = client.run("create a report")
print(result.result)      # "processed: create a report"
print(result.trace_id)    # "abc-123-def"

# Streaming
for event in client.run_stream("create a report"):
    print(f"[{event.type}] {event.data}")
```

### Resource Namespaces

```python
# System
status = await client.system.status_async()
config = await client.system.config_async()
metrics = await client.system.metrics_async()

# Chat
reply = await client.chat.run_async("Hello!", session_id="abc")

# Agents
result = await client.agents.run_async("agent-1", "analyze data")

# Secrets
await client.secrets.set_async("my-key", "my-value")
value = await client.secrets.get_async("my-key")
await client.secrets.delete_async("my-key")

# Governance
explanation = await client.governance.explain_async("WRITE", {"path": "/tmp/test"})
trace = await client.governance.trace_async("abc-123-def")
```

---

## Sync vs Async Guide

| Use Case | API | Mechanismus |
|----------|-----|-------------|
| Single Request (CLI/Script) | `Client.run()` | `_sync_await()` — einfache Coroutine-Bridge |
| Streaming (CLI/Script) | `Client.run_stream()` | Threaded Bridge — Queue + Worker Thread |
| Production App | `AsyncClient.*` | Native async/await (keine Bridge) |

**Empfehlung**: Nutze `AsyncClient` für alle production-grade Anwendungen. `Client` ist nur für CLI/Scripts gedacht, wo async nicht verfügbar ist.

---

## CLI

```bash
# Run a command
hestiaos run "create a report"

# Check server health
hestiaos health

# Retrieve a trace
hestiaos trace abc-123-def

# JSON output (pipe to jq)
hestiaos run "hello" --json | jq

# Custom server URL
hestiaos --base-url http://localhost:8000 health
```

| Command | Description |
|---------|-------------|
| `hestiaos run <text>` | Execute a command through the governance pipeline |
| `hestiaos trace <id>` | Retrieve a governance trace by ID |
| `hestiaos health` | Check server health status |

| Global Option | Description |
|---------------|-------------|
| `--base-url, -u` | API base URL (default: `http://localhost:8000`) |
| `--api-key, -k` | API key for authentication |
| `--json, -j` | Output as raw JSON |

---

## API Reference

### AsyncClient (Primary API)

| Method | Returns | Description |
|--------|---------|-------------|
| `run_async(input, session_id=None, ...)` | `RunResponse` | Execute through governance pipeline |
| `run(input, session_id=None, ...)` | `RunResponse` | Sync convenience wrapper |
| `run_stream(input, session_id=None, ...)` | `AsyncIterator[StreamEvent]` | Streaming execution |
| `chat.run_async(message, session_id=None)` | `ChatResponse` | Chat completion |
| `agents.run_async(agent_id, task, config=None)` | `AgentResult` | Agent execution |
| `system.status_async()` | `SystemStatus` | Server health status |
| `system.config_async()` | `dict` | Server configuration |
| `system.metrics_async()` | `SystemMetrics` | Server metrics |
| `secrets.get_async(key)` | `str` | Get secret value |
| `secrets.set_async(key, value, provider="custom")` | `None` | Set secret |
| `secrets.delete_async(key)` | `None` | Delete secret |
| `governance.explain_async(command_type, command_input)` | `dict` | Explain governance decision |
| `governance.status_async()` | `dict` | Governance status |
| `governance.trace_async(command_id)` | `dict \| None` | Retrieve governance trace |

### Client (Sync Facade)

| Method | Returns | Description |
|--------|---------|-------------|
| `run(input, session_id=None, ...)` | `RunResponse` | Execute through governance pipeline |
| `run_stream(input, session_id=None, ...)` | `Generator[StreamEvent]` | Streaming execution |
| `chat.run(message, session_id=None)` | `ChatResponse` | Chat completion |
| `agents.run(agent_id, task, config=None)` | `AgentResult` | Agent execution |
| `system.status()` | `SystemStatus` | Server health status |
| `system.config()` | `dict` | Server configuration |
| `system.metrics()` | `SystemMetrics` | Server metrics |
| `secrets.get(key)` | `str` | Get secret value |
| `secrets.set(key, value, provider="custom")` | `None` | Set secret |
| `secrets.delete(key)` | `None` | Delete secret |
| `governance.explain(command_type, command_input)` | `dict` | Explain governance decision |
| `governance.status()` | `dict` | Governance status |
| `governance.trace(command_id)` | `dict \| None` | Retrieve governance trace |

### StreamEvent

| Attribute | Type | Description |
|-----------|------|-------------|
| `type` | `Literal["start","token","delta","tool_call","final","error","done"]` | Event type |
| `data` | `dict[str, Any]` | Event payload |
| `trace_id` | `str` | Correlation ID |
| `timestamp` | `str` | ISO timestamp |

### Models

| Model | Fields |
|-------|--------|
| `RunResponse` | `result`, `trace_id`, `output`, `mode`, `budget`, `latency_ms` |
| `TraceResponse` | `trace_id`, `decision`, `violations`, `latency_ms` |
| `HealthResponse` | `status`, `version`, `uptime_seconds` |
| `ErrorResponse` | `error`, `code`, `message`, `trace_id` |
| `ChatResponse` | `result`, `session_id`, `trace_id` |
| `AgentResult` | `result`, `agent_id`, `trace_id` |
| `SystemStatus` | `status`, `version`, `uptime_seconds` |
| `SystemMetrics` | `metrics` |

### Exceptions

| Exception | HTTP Status | Description |
|-----------|-------------|-------------|
| `HestiaError` | — | Base exception |
| `GovernanceBlock` | 403 | Governance blocked execution |
| `InvalidInput` | 422 | Request schema invalid |
| `NotFound` | 404 | Resource not found |

---

## Behavioral Contract (frozen)

Das SDK v1.0.0 hat einen **ABI + Behavioral Contract Freeze**. Folgende Verhaltensweisen sind Teil des öffentlichen Vertrags und ändern sich nicht ohne Major-Version:

- **SSE Parsing**: Heartbeat-toleranter Parser, `line.split("data:", 1)[1].strip()` Extraktion.
- **Cancellation**: Cooperative (async), `threading.Event()` (sync), keine cleanup-Verzögerung.
- **Event-Reihenfolge**: `start → (token \| delta \| tool_call)* → (final \| error) → done`.
- **Transport**: `httpx.AsyncClient`, 30s Timeout, `hestiaos-sdk/{version}` User-Agent.

---

## Development

```bash
# Clone and install
git clone <repo-url> && cd hestiaos
python -m venv venv && source venv/bin/activate
pip install -e .

# Run tests
pytest tests/test_sdk_client.py tests/test_api_v1_contract.py tests/test_cli.py -v

# Contract Guard (no core.* imports in SDK)
python -m src.hestiaos.contract_guard

# Import test
python -c "from hestiaos import AsyncClient, Client, StreamEvent; print('SDK Import OK')"
```

---

## License

MIT — see [LICENSE](LICENSE).
