Metadata-Version: 2.4
Name: simpleopenai-proxy
Version: 0.1.2
Summary: Transparent OpenAI Chat Completions proxy and response normalizer
Project-URL: Homepage, https://github.com/yourname/simpleopenai-proxy
Project-URL: Repository, https://github.com/yourname/simpleopenai-proxy
Author-email: Your Name <you@example.com>
License: MIT
Keywords: chat-completions,glm,openai,proxy,sse
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: fastapi>=0.100
Requires-Dist: httpx>=0.27
Requires-Dist: uvicorn[standard]>=0.27
Description-Content-Type: text/markdown

# simpleopenai-proxy

A lightweight transparent proxy for OpenAI-compatible Chat Completions endpoints.

It sits in front of a non-standard upstream API and exposes a standard local OpenAI Chat Completions server. Currently it normalizes cases where upstream providers incorrectly emit empty strings (`""`) for `content` or `reasoning_content` instead of the expected OpenAI `null`.

## Install / run with uvx

```bash
uvx simpleopenai-proxy <source-api-address> <localport>
```

Example:

```bash
uvx simpleopenai-proxy https://api.example.com/v1/chat/completions 8080
```

The proxy transparently forwards all request headers (including `Authorization`) to the upstream endpoint, so clients use the local server exactly like a standard OpenAI endpoint:

```bash
curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <upstream-api-key>" \
  -d '{
    "model": "glm_5_dot_2_public",
    "messages": [{"role": "user", "content": "hello"}],
    "stream": true
  }'
```

## Run from source

```bash
uv run server.py <source-api-address> <localport>
```

## Current normalizations

- `choices[].message.content` → `null` when upstream sends `""`
- `choices[].message.reasoning_content` → `null` when upstream sends `""`
- `choices[].delta.content` → `null` when upstream sends `""` (streaming)
- `choices[].delta.reasoning_content` → `null` when upstream sends `""` (streaming)
- SSE lines without a space after `data:` are parsed and re-emitted as standard `data: {...}`

## Development

```bash
uv run python -m unittest discover tests
```
