Metadata-Version: 2.4
Name: medsplain
Version: 0.1.0
Summary: Official Python client for the Medsplain TX medical text simplification API
Project-URL: Homepage, https://github.com/medsplain/medsplain-python
Project-URL: Documentation, https://github.com/medsplain/medsplain-python#readme
Project-URL: Issues, https://github.com/medsplain/medsplain-python/issues
Author: Medsplain TX
License: MIT
License-File: LICENSE
Keywords: api,client,medical,medsplain,sdk,text-simplification
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Healthcare Industry
Classifier: License :: OSI Approved :: MIT License
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 :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Description-Content-Type: text/markdown

# Medsplain TX — Python SDK

Official Python client for the **Medsplain TX** medical text simplification API. Send
clinical / medical text and get back a plain-language explanation.

## Installation

```bash
pip install medsplain
```

> Until this is published to PyPI, install from source — see [Local development](#local-development).

## Quick start

```python
from medsplain import Medsplain

client = Medsplain(api_key="mds_live_...")

result = client.translate("Patient presents with acute myocardial infarction.")
print(result.simplified_text)
print(f"{result.source_chars} chars in, {result.output_chars} chars out")
```

The client is a context manager, which closes the connection pool for you:

```python
with Medsplain(api_key="mds_live_...") as client:
    result = client.translate("CBC shows leukocytosis with left shift.")
    print(result.simplified_text)
```

## Configuration

| Argument      | Env var              | Default                  | Notes                                              |
| ------------- | -------------------- | ------------------------ | -------------------------------------------------- |
| `api_key`     | `MEDSPLAIN_API_KEY`  | —                        | Required. Your `mds_live_` key.                    |
| `base_url`    | `MEDSPLAIN_BASE_URL` | `http://localhost:8000`  | API root, **without** the `/v1` prefix.            |
| `timeout`     | —                    | `30.0`                   | Per-request timeout in seconds.                    |
| `max_retries` | —                    | `2`                      | Retries on connection errors, `429`, and `5xx`.    |

```python
import os
client = Medsplain(
    api_key=os.environ["MEDSPLAIN_API_KEY"],
    base_url="https://your-medsplain-host.example.com",
    timeout=60.0,
)
```

## API

### `translate(text, *, model=None) -> TranslationResult`
Simplify medical text using the Claude-backed endpoint (`POST /v1/translate`).
`text` must be non-empty and at most **5000 characters**.

### `translate_gemini(text, *, model=None) -> TranslationResult`
Same contract, backed by Gemini (`POST /v1/translate_test_gemini`).

### `health_check() -> HealthStatus`
Verify the API is reachable (`GET /health-check`).

### `TranslationResult`
| Field             | Type   | Description                                       |
| ----------------- | ------ | ------------------------------------------------- |
| `original_text`   | `str`  | Cleaned input text the server processed.          |
| `simplified_text` | `str`  | The plain-language simplification.                |
| `source_chars`    | `int`  | Character count of the input.                     |
| `output_chars`    | `int`  | Character count of the output.                    |
| `is_medical_text` | `bool` | Whether the input was detected as medical.        |
| `is_conversation` | `bool` | Whether the input was detected as conversational. |
| `raw`             | `dict` | Full, unmodified response payload.                |

## Error handling

Every error inherits from `MedsplainError`. HTTP failures raise an `APIStatusError`
subclass chosen by status code:

```python
from medsplain import (
    Medsplain, AuthenticationError, RateLimitError,
    PermissionDeniedError, APIStatusError,
)

client = Medsplain(api_key="mds_live_...")
try:
    result = client.translate("...")
except AuthenticationError:
    ...                       # 401 — key missing/invalid/expired/revoked
except RateLimitError as e:
    print("retry after", e.retry_after)   # 429 — rate limit or token quota
except PermissionDeniedError:
    ...                       # 403 — no active plan / subscription
except APIStatusError as e:
    print(e.status_code, e.code, e.message)
```

| Exception               | Status | Meaning                                          |
| ----------------------- | ------ | ------------------------------------------------ |
| `BadRequestError`       | 400    | Malformed request / validation error.            |
| `AuthenticationError`   | 401    | API key missing, invalid, expired, or revoked.   |
| `PermissionDeniedError` | 403    | No active plan or subscription.                  |
| `NotFoundError`         | 404    | Resource not found.                              |
| `RateLimitError`        | 429    | Rate limit hit or token quota exhausted.         |
| `ServerError`           | 5xx    | Server-side failure.                             |
| `APIConnectionError`    | —      | The request never reached the server.            |

## Local development

```bash
cd sdk
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -e ".[dev]"

pytest                              # run tests
ruff check .                        # lint
mypy src/                           # type-check
python -m build                     # build wheel + sdist into dist/
```

## License

MIT — see [LICENSE](LICENSE).
