Metadata-Version: 2.5
Name: mnfst-autofix
Version: 0.1.0
Summary: Self-healing HTTP transport for LLM SDKs - the OpenAI and Anthropic Python SDKs. Fixes request-side failures at runtime (renamed params, restricted values, retired models) and retries. Anonymized: your prompts never travel in the request.
Project-URL: Homepage, https://github.com/mnfst/autofix#readme
Project-URL: Repository, https://github.com/mnfst/autofix
Author: Manifest
License-Expression: MIT
License-File: LICENSE
Keywords: anthropic,autofix,httpx,llm,openai,reliability,retry,self-healing
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: anthropic>=0.25; extra == 'dev'
Requires-Dist: openai>=1.40; extra == 'dev'
Requires-Dist: pytest-cov>=4; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# Autofix Python

Self-healing HTTP transport for LLM SDKs — the [OpenAI](https://github.com/openai/openai-python) and [Anthropic](https://github.com/anthropics/anthropic-sdk-python) Python SDKs. When a request fails with a fixable request-shape error — a renamed parameter, a restricted value, a retired model — autofix repairs it at runtime and retries. Your code doesn't change; your users never see the failure.

## Installation

Use one import per SDK. Routing follows the request path, including custom
`base_url` values.

```bash
pip install mnfst-autofix
```

The hosted demo uses `https://phoenix-yc-production.up.railway.app`. Set
`AUTOFIX_API_KEY` in your application environment (or `.env` when your runtime
loads it) to authenticate heal requests. Use `AUTOFIX_URL` to override the
endpoint.

## Usage

```python
from openai import OpenAI
from mnfst_autofix.openai import autofix

client = OpenAI(http_client=autofix())

res = client.chat.completions.create(
    model="gpt-5-mini",
    temperature=0.2,  # gpt-5 models reject this - normally a 400
    messages=[{"role": "user", "content": "Hello!"}],
)
# -> healed at runtime (temperature set to 1), returns a normal 200
```

That's the whole integration — every call on this client is self-healing.

Async works the same way:

```python
from openai import AsyncOpenAI
from mnfst_autofix.openai import autofix_async

client = AsyncOpenAI(http_client=autofix_async())
```

For Anthropic:

```python
from anthropic import Anthropic
from mnfst_autofix.anthropic import autofix

client = Anthropic(http_client=autofix())
```

For LiteLLM:

```python
from openai import OpenAI
from mnfst_autofix.openai import autofix

client = OpenAI(
    base_url="http://localhost:4000/v1",
    http_client=autofix(),
)
```

## How it works

On a `400`, `404` or `422`, autofix applies the privacy filter described below, asks the heal API for the current fix, applies it, and replays once. Anything goes wrong → your original error, unchanged.

## Never worse than without it

- **Zero overhead on success** — the transport only wakes up on a healable failure.
- **Fail open** — heal API down, slow, or out of ideas: you get the original error. The heal call has a 5s budget, so it can't sit on top of a failure you're already waiting for.
- **Your key never leaves** — the provider API key stays on your SDK's request, on its original path.

## Privacy

The heal API receives settings, not prompt data:

```jsonc
// sent to the heal API
{
  "model": "gpt-5-mini",
  "temperature": 0.2
}

// kept local and restored on replay
{
  "messages": [{ "role": "user", "content": "Hello!" }],
  "tools": [...]
}
```

Scalar settings and scalar-only arrays may travel. Prompts, tools, nested arrays,
schema bodies, identity fields, and credential fields stay local. The provider error,
endpoint origin and path, derived workspace id, and SDK source are also sent.

`autofix(send_messages=True)` (default `False`) opts the top-level `messages`
list in, verbatim — for teams pointing at their own heal service who want the
conversation visible next to the failure it caused. It is observability only:
the heal API still cannot author or rewrite a message on the way back.

## See heals

```python
client = OpenAI(
    http_client=autofix(
        on_heal=lambda event: print(event.heal_status, event.summary),
    ),
)
```

## License

MIT © Manifest
