shim-sdk 0.1.0
Official Python SDK for Shim — JSON repair for LLM outputs
Requires Python: >=3.9
Keywords: anthropic, json, llm, openai, repair, shim, validation

# shim-sdk

Python SDK for [Shim](https://shim.so). Intercept malformed JSON from LLMs. Repair it. Return valid data.

One dependency: `httpx`. Sync and async clients included.

## Installation

```bash
pip install shim-sdk
```

```bash
# Poetry
poetry add shim-sdk
```

```bash
# uv
uv add shim-sdk
```

## Quick Start

```python
from shim import ShimClient

with ShimClient(api_key="sk_live_...") as shim:
    result = shim.repair(raw_output='{"name": "John", "age": 30')

    if result.success:
        print(result.repaired)  # {'name': 'John', 'age': 30}
```

## Async

```python
from shim import AsyncShimClient

async with AsyncShimClient(api_key="sk_live_...") as shim:
    result = await shim.repair(raw_output='{"name": "John", "age": 30')
    print(result.repaired)
```

## Schema Validation

Pass a JSON Schema to enforce types. Shim coerces values and reports what it changed.

```python
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age":  {"type": "number"}
    },
    "required": ["name", "age"]
}

with ShimClient(api_key="sk_live_...") as shim:
    result = shim.repair(
        raw_output='{"name": "John", "age": "30"',
        schema=schema,
        mode="strict"
    )

    print(result.repaired)             # {'name': 'John', 'age': 30}
    print(result.metadata.confidence)  # 'medium' — schema repair present
```

## Streaming

Schema and mode are set at `stream.start()`. Push chunks as they arrive. Finalize when the stream ends.

```python
from shim import ShimClient

with ShimClient(api_key="sk_live_...") as shim:
    session = shim.stream.start(
        schema={"type": "object", "properties": {"name": {"type": "string"}}},
        mode="strict"
    )

    # Push chunks as they arrive from LLM
    shim.stream.push(session.session_id, '{"name": "Jo')
    shim.stream.push(session.session_id, 'hn", "age": 30')

    # Finalize when stream ends
    result = shim.stream.finalize(session.session_id)
    print(result.repaired)  # {'name': 'John', 'age': 30}
```

### Async streaming

```python
from shim import AsyncShimClient

async with AsyncShimClient(api_key="sk_live_...") as shim:
    session = await shim.stream.start()

    await shim.stream.push(session.session_id, '{"name": "Jo')
    await shim.stream.push(session.session_id, 'hn", "age": 30')

    result = await shim.stream.finalize(session.session_id)
    print(result.repaired)  # {'name': 'John', 'age': 30}
```

## Error Handling

The SDK raises `httpx.HTTPStatusError` for transport-level failures. Shim itself always returns HTTP 200 — application errors are in the response body.

```python
import httpx
from shim import ShimClient

with ShimClient(api_key="sk_live_...") as shim:
    try:
        result = shim.repair(raw_output="not json at all")

        if not result.success:
            for error in result.metadata.errors:
                print(f"{error.code}: {error.message}")
                print(f"  recoverable: {error.recoverable}")
    except httpx.HTTPStatusError as e:
        print(f"Transport error: {e.response.status_code}")
```

## Types

Full type definitions included. All response objects are dataclasses with autocomplete.

| Type | Description |
|------|-------------|
| `RepairResponse` | Top-level batch / finalize response |
| `RepairMetadata` | Confidence, repairs, warnings, errors |
| `RepairDetail` | Single repair operation (type, confidence, field) |
| `Warning` | Non-critical issue |
| `RepairError` | Critical failure with recoverability flag |
| `StreamSession` | Session ID + expiry from `stream.start()` |
| `StreamingState` | Incremental parse state from `stream.push()` |

## Support

- Docs: [docs.shim.so](https://docs.shim.so)
- Issues: [GitHub Issues](https://github.com/shimso/shim-core/issues)

## License

MIT