Metadata-Version: 2.4
Name: tokensaver-sdk
Version: 0.1.0
Summary: Python SDK for the TokenSaver API: pipelines, chat sessions, and pricing estimates
Author: TokenSaver
License-Expression: MIT
Project-URL: Documentation, https://github.com/MemIA-AI/tokensaver-platform
Project-URL: Repository, https://github.com/MemIA-AI/tokensaver-platform
Keywords: tokensaver,llm,api,client
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<0.28,>=0.26.0
Requires-Dist: pydantic>=2.5.0
Provides-Extra: dev
Requires-Dist: build>=1.0.0; extra == "dev"
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-httpx>=0.28.0; extra == "dev"
Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: twine>=5.0.0; extra == "dev"
Dynamic: license-file

# TokenSaver SDK

Python client for the **TokenSaver API** (`POST /pipelines/run`, RAG, chat sessions, pricing).  
Only HTTP transport and response normalization run in this package; **all pipeline logic stays on the server**.

**Doc d’architecture (monorepo)** : [`docs/ARCHITECTURE-SDK-TOKENSAVER.md`](../../docs/ARCHITECTURE-SDK-TOKENSAVER.md)

## Installation

```bash
pip install tokensaver-sdk
```

Développement dans le monorepo :

```bash
cd packages/sdk
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
```

## Configuration

- **`api_key`** (obligatoire) : clé TokenSaver (`ts_...`).
- **`base_url`** (optionnel) : point d’entrée API ; défaut **`https://platform.tokensaver.fr/api/v1`**.
- **`provider_api_key`** (optionnel) : clé LLM du fournisseur (`openai`, `anthropic`, etc.) envoyée **à chaque** `ask` / `run_pipeline` si définie ici ; prioritaire sur les clés enregistrées en base pour ce run uniquement ; **jamais** stockée côté TokenSaver. Tu peux aussi passer `provider_api_key=` sur un appel ponctuel.

```python
from tokensaver_sdk import TokenSaver

ts = TokenSaver(api_key="ts_...")
# Backend local :
# ts = TokenSaver(api_key="ts_...", base_url="http://localhost:8000/api/v1")
# Clé LLM par défaut pour tous les runs (optionnel) :
# ts = TokenSaver(api_key="ts_...", provider_api_key="sk-...")
```

## Appel pipeline (`ask` / `run_pipeline`)

`ask()` renvoie un **`RunResult`** (`.text`, `.metrics`, `.trace`, `.context`).  
`run_pipeline()` renvoie le **JSON brut** de l’API.

**Flags de modules** (désactivés par défaut côté SDK, comme en console) :  
`use_cache`, `use_rag`, `use_compression`, `use_pii_filter`, `stream`.

**Paramètres avancés** (alignés sur `PipelineRunRequest` / console) — passés tels quels au JSON :

| Paramètre | Usage |
|-----------|--------|
| `temperature` | Température LLM (0–2). |
| `rag_similarity_threshold` | Seuil similarité RAG (0–1). |
| `cache_similarity_threshold` | Seuil similarité cache sémantique (0–1). |
| `compression_level` | Niveau compression 1–5. |
| `rag_options` | Dict : `document_ids`, `top_k`, `query_image_url`. |
| `pii_options` | Dict : `engine`, `strategy`, `confidence_threshold`, `entity_types`, `language`, `regex_fallback`. |
| `context_layers` | Format canonique (instructions, knowledge, interaction, `token_budget`). |
| `system_prompt`, `profile_context`, `workspace_instructions` | Champs plats historiques (si pas de `context_layers`). |
| `provider_api_key` | **SDK** : clé LLM éphémère pour ce run ; priorité sur la BDD ; non persistée. |

Types d’aide pour l’IDE : `from tokensaver_sdk import RagOptions, PiiOptions` (`TypedDict`).

```python
result = ts.ask(
    "Your question",
    provider="openai",
    model="gpt-4o",
    use_rag=True,
    rag_similarity_threshold=0.55,
    rag_options={"document_ids": ["uuid-doc"], "top_k": 8},
)
```

## RAG (documents)

| Méthode | Rôle |
|---------|------|
| `rag_list_documents()` | Liste les PDF du workspace. |
| `rag_upload_document(path, …)` | Upload multipart (sans attente). Lève `ValidationError` (`RAG_FILE_NOT_FOUND`) si le fichier est absent. |
| `rag_get_document(id)` | Statut / métadonnées. |
| `rag_wait_document_ready(id, …)` | Attente ingestion. |
| `rag_upload_and_wait(path, …)` | Upload + attente. |
| `rag_ensure_document(path, …)` | Réutilise un fichier déjà ingéré (même **nom de fichier**) ou upload + attente. |

Exemple minimal avec question sur un PDF :

```python
doc = ts.rag_ensure_document("handbook.pdf")
ts.ask(
    "What are the key points?",
    provider="openai",
    model="gpt-4o",
    use_rag=True,
    rag_options={"document_ids": [doc["document_id"]]},
)
```

## Sessions chat

```python
from tokensaver_sdk import HISTORY_NONE, HISTORY_LOCAL, HISTORY_SERVER

# Stateless (défaut de ask : history=HISTORY_NONE)
ts.ask("…", provider="openai", model="gpt-4o", history=HISTORY_NONE)

# Persistance serveur
session = ts.chat.session(history=HISTORY_SERVER, name="My chat")
session.ask("…", provider="openai", model="gpt-4o")
```

## Estimation de coût (sans appel LLM)

```python
ts.estimate_cost(1200, 300, provider="openai", model="gpt-4o")
```

## Erreurs

```python
from tokensaver_sdk import ERROR_RAG_FILE_NOT_FOUND
from tokensaver_sdk.errors import (
    TokenSaverError,
    AuthenticationError,
    ProviderKeyMissingError,
    QuotaExceededError,
    RateLimitError,
    ValidationError,
    ServerError,
    TimeoutError,
)
```

Les erreurs HTTP sont mappées vers ces exceptions. Pour les uploads RAG (`rag_upload_document`, `rag_upload_and_wait`, `rag_ensure_document` quand un fichier est envoyé), un chemin PDF inexistant côté client lève `ValidationError` avec `code="RAG_FILE_NOT_FOUND"` (comparer à `ERROR_RAG_FILE_NOT_FOUND`) ; le champ `raw` contient notamment `"path"`.

## Tests & qualité

```bash
pytest
ruff check src tests && ruff format src tests
```

Variables utiles pour des tests d’intégration : `TOKENSAVER_API_KEY`, URL de base selon votre déploiement.

## Publication sur PyPI

1. **Version** : mettre à jour `__version__` dans `src/tokensaver_sdk/__init__.py` (seule source de vérité pour le build).
2. **Build & contrôle** : `python -m build` puis `twine check dist/*` (dépendances dev : `pip install -e ".[dev]"`).
3. **Upload** : `twine upload dist/*` (identifiant PyPI : `__token__`, mot de passe : le jeton API). TestPyPI possible en premier avec `--repository testpypi`.
4. **CI** : après ajout du secret dépôt **`PYPI_API_TOKEN`**, pousser un tag `sdk-v0.1.0` (même numéro que `__version__`) déclenche le workflow **Publish SDK to PyPI**.

## Référence détaillée

- **Console TokenSaver** : page *API Reference* (exemples, liste des méthodes SDK).
- **Architecture & décisions** : `docs/ARCHITECTURE-SDK-TOKENSAVER.md`.
