Metadata-Version: 2.4
Name: nage-ai
Version: 0.1.1
Summary: Official Python SDK for Nage — source-attributed AI on SEDIM
Author-email: Nage AI <one@nage.ai>
License-Expression: Apache-2.0
Project-URL: Homepage, https://nage.ai
Project-URL: Documentation, https://nage.ai/docs
Project-URL: Repository, https://github.com/NageAI/nage-platform
Project-URL: Changelog, https://nage.ai/changelog
Project-URL: Issues, https://github.com/NageAI/nage-platform/issues
Keywords: llm,ai,sedim,varve,source-attribution,stemma
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
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: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.25.0
Provides-Extra: async
Requires-Dist: anyio>=4.0; extra == "async"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-httpx>=0.30; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"

# nage-ai — Python SDK

Official Python client for [Nage](https://nage.ai) — source-attributed AI on the SEDIM architecture.

```bash
pip install nage-ai
```

(Package is published as `nage-ai`; import stays as `nage`.)

## Why Nage

Every response ships with a **STEMMA** — a real-time attribution map
showing which source contributed how much. For regulated teams
(legal, compliance, finance, healthcare) where "the model said so"
isn't a good answer, STEMMA is how you defend every claim.

## Quickstart

```python
from nage import Nage

client = Nage(api_key="nk_live_...")     # or set NAGE_API_KEY env var

r = client.think(
    query="Explain the GDPR right to erasure",
    platform="nm/fehm",
    inference_mode="top_k",
)

print(r.text)
print(r.stemma.weights)       # {'fehm-en': 0.71, 'cortex-reasoning': 0.21, ...}
print(r.stemma.dominant_varve) # 'fehm-en'
print(r.stemma.entropy)        # 0.52
print(r.latency_ms)            # 847
```

## VARVE management

```python
for v in client.varves.list():
    print(v.name, v.status, v.rank)

health = client.varves.health("<varve-id>")
# health.status ∈ {'optimal', 'weak', 'collapsed', 'overtrained', 'unknown'}
# health.rho — orbital ρ (want [0.05, 0.30])

# GDPR / KVKK Article 17 surgical removal
client.varves.privacy_delete("<varve-id>")
```

## Upload + train a VARVE

```python
varve = client.ingest.upload_and_train(
    file_path="./contracts/q1-2026.pdf",
    name="contracts-q1-2026",
    layer="FEHM",
    varve_type="flash",     # 'ephemeral' | 'flash' | 'full'
    wait_for_ready=True,    # poll until training completes
)
print(varve.id, varve.status)
```

## Streaming conversation context

```python
# Multi-turn conversation — pass prior messages as context
context = []
for turn in ["Hello", "What's STEMMA?"]:
    r = client.think(query=turn, context=context)
    context.append({"role": "user", "content": turn})
    context.append({"role": "assistant", "content": r.text})
    print(f"> {turn}\n{r.text}\n")
```

## Error handling

All errors inherit from `NageError`:

```python
from nage import Nage, RateLimitError, AuthError, NageError

try:
    r = client.think(query="...")
except RateLimitError as e:
    print(f"Rate-limited. Retry after {e.retry_after}s.")
except AuthError as e:
    print(f"Auth: {e}")
except NageError as e:
    print(f"Other: {e.status} — {e.body}")
```

The client retries 429 and 5xx automatically (up to `max_retries=3`,
exponential backoff with jitter). You only see these if the retries
exhaust.

## Configuration

```python
client = Nage(
    api_key="nk_live_...",         # or NAGE_API_KEY env var
    base_url="https://api.sedim.ai", # or NAGE_BASE_URL env var
    timeout_s=90,                   # cold-start can hit ~30s
    max_retries=3,
)
```

You can also authenticate with a user JWT (for platform-scoped operations
like Canvas editing):

```python
client = Nage(bearer_token="<jwt>")
```

## Context manager

```python
with Nage(api_key="nk_live_...") as client:
    r = client.think(query="...")
# Connection closed automatically
```

## Links

- **Platform:** https://nage.ai
- **Docs:** https://nage.ai/docs
- **Dashboard + keys:** https://nage.ai/dashboard
- **Status:** https://nage.ai/status
- **GitHub:** https://github.com/NageAI

## License

Apache-2.0
