Codex Convert Proxy
A high-performance proxy service that converts between OpenAI Responses API (used by Codex) and Chat Completions API (used by Chinese LLM providers).
Background
Codex 0.118+ uses the Responses API, but most Chinese LLM providers (GLM, Kimi, DeepSeek, MiniMax) only support the Chat Completions API. This proxy bridges the gap by performing bidirectional format conversion.
Architecture
┌─────────────┐ Responses API ┌──────────────────┐ Chat API ┌─────────────────┐
│ Codex │ ──────────────────▶ │ codex-convert- │ ──────────▶ │ LLM Provider │
│ Client │ ◀────────────────── │ proxy │ ◀────────── │ (GLM/Kimi/...) │
└─────────────┘ Responses API └──────────────────┘ SSE/JSON └─────────────────┘
Features
- Multi-backend routing: Route requests to different LLM providers based on path prefix
- Protocol conversion: Responses API ↔ Chat API bidirectional conversion
- Streaming SSE support: Real-time conversion of Server-Sent Events
- Provider-specific handling: Per-provider request/response transformation
- OpenTelemetry tracing: Built-in observability support
- TLS support: Secure upstream connections via rustls
Supported Providers
| Provider | Model | API Path | Notes |
|---|---|---|---|
| GLM (Zhipu AI) | glm-4, glm-5 | /chat/completions |
Removes tools, flattens content |
| Kimi (Moonshot) | moonshot-v1-* | /v1/chat/completions |
OpenAI compatible |
| DeepSeek | deepseek-chat | /v1/chat/completions |
OpenAI compatible |
| MiniMax | ab-01, ab-02 | /v1/chat/completions |
Flattens content, converts developer role |
Quick Start
1. Configure
Edit config.json:
2. Build & Run
# Development
# Production
Or use Make:
3. Test with Codex
# Set Codex endpoint
# Or use codex exec with proxy
Configuration Reference
Backend Configuration
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Backend identifier |
url |
string | Yes | Upstream API base URL |
api_key |
string | Yes | API authentication key |
model |
string | Yes | Model name to use with this backend |
protocol |
string | Yes | Currently only "openai" is supported |
match_rules.path_prefix |
string | No | Route requests by path prefix |
match_rules.default |
boolean | No | Set as default backend |
Match Rules
Requests are routed based on match_rules:
- path_prefix: Matches if request path starts with the prefix (e.g.,
/kimi→kimibackend) - default: The fallback backend when no prefix matches
API Endpoints
The proxy handles the Responses API format at the root path:
| Method | Path | Description |
|---|---|---|
| POST | / |
Convert and forward Responses API request |
| GET | /health |
Health check |
Provider-Specific Handling
GLM
- API path:
/chat/completions(not/v1/chat/completions) - Removes
toolsandtool_choicefrom requests (not supported) - Converts
developerrole touser - Flattens content array to string
MiniMax
- Converts
developerrole touser - Flattens content array to string
- Ensures response content is string format
Kimi / DeepSeek
- Fully OpenAI Chat API compatible
- No special transformation needed
Monitoring
Logs
Logs are written to the configured log_dir:
./logs/
├── codex-convert-proxy.log
└── error.log
OpenTelemetry
Configure OTLP endpoint for tracing:
Development
# Run tests
# Run with debug logging
RUST_LOG=debug
# Build release
Project Structure
src/
├── main.rs # CLI entry point
├── lib.rs # Library exports
├── config.rs # Configuration loading
├── proxy/
│ └── proxy_impl.rs # Pingora ProxyHttp implementation
├── providers/
│ ├── trait_.rs # Provider trait definition
│ ├── glm.rs # GLM provider
│ ├── kimi.rs # Kimi/Moonshot provider
│ ├── deepseek.rs # DeepSeek provider
│ └── minimax.rs # MiniMax provider
├── convert/
│ ├── request.rs # Responses → Chat API conversion
│ ├── response.rs # Chat → Responses API conversion
│ └── streaming.rs # SSE streaming conversion
├── types/
│ ├── chat_api.rs # Chat API types
│ └── response_api.rs # Responses API types
├── streaming.rs # SSE parsing utilities
├── server.rs # Pingora server setup
├── stats.rs # Request statistics
├── telemetry.rs # OpenTelemetry setup
├── logger.rs # Logging configuration
└── error.rs # Error types
License
MIT