codex-as-api 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codex_as_api-0.2.1/.gitignore +11 -0
- codex_as_api-0.2.1/PKG-INFO +543 -0
- codex_as_api-0.2.1/README.md +514 -0
- codex_as_api-0.2.1/pyproject.toml +53 -0
- codex_as_api-0.2.1/requirements-server.txt +3 -0
- codex_as_api-0.2.1/requirements.txt +6 -0
- codex_as_api-0.2.1/rust/Cargo.lock +2009 -0
- codex_as_api-0.2.1/rust/Cargo.toml +21 -0
- codex_as_api-0.2.1/rust/src/anthropic_adapter.rs +1255 -0
- codex_as_api-0.2.1/rust/src/auth.rs +556 -0
- codex_as_api-0.2.1/rust/src/main.rs +49 -0
- codex_as_api-0.2.1/rust/src/messages.rs +236 -0
- codex_as_api-0.2.1/rust/src/protocol.rs +347 -0
- codex_as_api-0.2.1/rust/src/provider.rs +1382 -0
- codex_as_api-0.2.1/rust/src/server.rs +878 -0
- codex_as_api-0.2.1/src/codex_as_api/__init__.py +3 -0
- codex_as_api-0.2.1/src/codex_as_api/anthropic_adapter.py +447 -0
- codex_as_api-0.2.1/src/codex_as_api/auth.py +239 -0
- codex_as_api-0.2.1/src/codex_as_api/messages.py +116 -0
- codex_as_api-0.2.1/src/codex_as_api/protocol.py +98 -0
- codex_as_api-0.2.1/src/codex_as_api/provider.py +701 -0
- codex_as_api-0.2.1/src/codex_as_api/server.py +580 -0
- codex_as_api-0.2.1/tests/__init__.py +0 -0
- codex_as_api-0.2.1/tests/conftest.py +53 -0
- codex_as_api-0.2.1/tests/test_anthropic_adapter.py +502 -0
- codex_as_api-0.2.1/tests/test_auth.py +277 -0
- codex_as_api-0.2.1/tests/test_messages.py +203 -0
- codex_as_api-0.2.1/tests/test_protocol.py +209 -0
- codex_as_api-0.2.1/tests/test_provider.py +437 -0
- codex_as_api-0.2.1/tests/test_server.py +144 -0
- codex_as_api-0.2.1/ts/.npmrc +1 -0
- codex_as_api-0.2.1/ts/package-lock.json +2457 -0
- codex_as_api-0.2.1/ts/package.json +55 -0
- codex_as_api-0.2.1/ts/src/__tests__/anthropic-adapter.test.ts +490 -0
- codex_as_api-0.2.1/ts/src/__tests__/auth.test.ts +230 -0
- codex_as_api-0.2.1/ts/src/__tests__/protocol.test.ts +173 -0
- codex_as_api-0.2.1/ts/src/__tests__/provider.test.ts +513 -0
- codex_as_api-0.2.1/ts/src/anthropic-adapter.ts +478 -0
- codex_as_api-0.2.1/ts/src/auth.ts +291 -0
- codex_as_api-0.2.1/ts/src/cli.ts +3 -0
- codex_as_api-0.2.1/ts/src/index.ts +39 -0
- codex_as_api-0.2.1/ts/src/messages.ts +44 -0
- codex_as_api-0.2.1/ts/src/protocol.ts +91 -0
- codex_as_api-0.2.1/ts/src/provider.ts +927 -0
- codex_as_api-0.2.1/ts/src/server.ts +581 -0
- codex_as_api-0.2.1/ts/tsconfig.json +17 -0
- codex_as_api-0.2.1/ts/tsup.config.ts +18 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codex-as-api
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Use ChatGPT/Codex OAuth as a local OpenAI-compatible API server.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Eunho-J/codex-as-api
|
|
6
|
+
Project-URL: Repository, https://github.com/Eunho-J/codex-as-api
|
|
7
|
+
Author: Eunho-J
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
Keywords: api,chatgpt,codex,llm,oauth,openai
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
24
|
+
Provides-Extra: server
|
|
25
|
+
Requires-Dist: fastapi>=0.100; extra == 'server'
|
|
26
|
+
Requires-Dist: pydantic>=2.0; extra == 'server'
|
|
27
|
+
Requires-Dist: uvicorn>=0.23; extra == 'server'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# codex-as-api
|
|
31
|
+
|
|
32
|
+
Use ChatGPT / Codex OAuth as a local OpenAI-compatible API server.
|
|
33
|
+
|
|
34
|
+
## What it does
|
|
35
|
+
|
|
36
|
+
Runs a lightweight HTTP server on `localhost` that translates standard OpenAI API calls into authenticated requests against the ChatGPT / Codex backend using your existing `~/.codex/auth.json` OAuth credentials. Supports streaming, tool calling, reasoning, image generation, and Codex-specific features like `prompt_cache_key` and subagent headers.
|
|
37
|
+
|
|
38
|
+
Python, Rust, and TypeScript (npm) implementations are provided — identical functionality, same endpoints, same behavior.
|
|
39
|
+
|
|
40
|
+
## Prerequisites
|
|
41
|
+
|
|
42
|
+
Install the official Codex CLI and log in so that `~/.codex/auth.json` exists:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install -g @openai/codex
|
|
46
|
+
codex login
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The server reads that file to obtain and refresh ChatGPT OAuth tokens automatically.
|
|
50
|
+
|
|
51
|
+
## Install & Run
|
|
52
|
+
|
|
53
|
+
### Python
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/Eunho-J/codex-as-api.git
|
|
57
|
+
cd codex-as-api
|
|
58
|
+
pip install -e ".[server]"
|
|
59
|
+
codex-as-api
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or with `uv`:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
uv pip install -e ".[server]"
|
|
66
|
+
codex-as-api
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Rust
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd rust
|
|
73
|
+
cargo build --release
|
|
74
|
+
./target/release/codex-as-api
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### TypeScript (npm)
|
|
78
|
+
|
|
79
|
+
Install from npm and run:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install -g codex-as-api
|
|
83
|
+
codex-as-api
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Or use `npx` without installing:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npx codex-as-api
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Or from source:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
cd ts
|
|
96
|
+
npm install
|
|
97
|
+
npm run build
|
|
98
|
+
node dist/cli.js
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Can also be used as a library:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { ChatGPTOAuthProvider, createApp } from "codex-as-api";
|
|
105
|
+
|
|
106
|
+
// Use the provider directly
|
|
107
|
+
const provider = new ChatGPTOAuthProvider({ model: "gpt-5.5" });
|
|
108
|
+
const response = await provider.chat(
|
|
109
|
+
[
|
|
110
|
+
{ role: "system", content: "You are helpful." },
|
|
111
|
+
{ role: "user", content: "Hello!" },
|
|
112
|
+
],
|
|
113
|
+
);
|
|
114
|
+
console.log(response.content);
|
|
115
|
+
|
|
116
|
+
// Or create an Express app
|
|
117
|
+
const app = createApp();
|
|
118
|
+
app.listen(18080);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
All versions bind to `127.0.0.1:18080` (localhost only) by default.
|
|
122
|
+
|
|
123
|
+
## Configuration
|
|
124
|
+
|
|
125
|
+
Environment variables (Python, Rust, and TypeScript):
|
|
126
|
+
|
|
127
|
+
| Variable | Default | Description |
|
|
128
|
+
|----------|---------|-------------|
|
|
129
|
+
| `CODEX_AS_API_HOST` | `127.0.0.1` | Bind address |
|
|
130
|
+
| `CODEX_AS_API_PORT` | `18080` | Listen port |
|
|
131
|
+
| `CODEX_AS_API_MODEL` | `gpt-5.5` | Model identifier passed to Codex backend |
|
|
132
|
+
| `CODEX_AS_API_AUTH_PATH` | `~/.codex/auth.json` | Path to OAuth credentials file |
|
|
133
|
+
|
|
134
|
+
### Supported Models
|
|
135
|
+
|
|
136
|
+
| Model | Description |
|
|
137
|
+
|-------|-------------|
|
|
138
|
+
| `gpt-5.5` | Frontier model for complex coding, research, and real-world work |
|
|
139
|
+
| `gpt-5.4` | Strong model for everyday coding |
|
|
140
|
+
| `gpt-5.4-mini` | Small, fast, and cost-efficient model for simpler coding tasks |
|
|
141
|
+
| `gpt-5.3-codex` | Coding-optimized model |
|
|
142
|
+
| `gpt-5.3-codex-spark` | Ultra-fast coding model |
|
|
143
|
+
| `gpt-5.2` | Previous generation model |
|
|
144
|
+
|
|
145
|
+
To use a different port:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
CODEX_AS_API_PORT=9000 codex-as-api
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
To expose on all interfaces (e.g. for remote access):
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
CODEX_AS_API_HOST=0.0.0.0 codex-as-api
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## API Endpoints
|
|
158
|
+
|
|
159
|
+
### `POST /v1/chat/completions`
|
|
160
|
+
|
|
161
|
+
Standard OpenAI chat completions. Supports streaming (`stream: true`) and non-streaming.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
165
|
+
-H "Content-Type: application/json" \
|
|
166
|
+
-d '{
|
|
167
|
+
"model": "gpt-5.5",
|
|
168
|
+
"messages": [
|
|
169
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
170
|
+
{"role": "user", "content": "Hello"}
|
|
171
|
+
]
|
|
172
|
+
}'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Streaming:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
179
|
+
-H "Content-Type: application/json" \
|
|
180
|
+
-d '{
|
|
181
|
+
"model": "gpt-5.5",
|
|
182
|
+
"messages": [
|
|
183
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
184
|
+
{"role": "user", "content": "Hello"}
|
|
185
|
+
],
|
|
186
|
+
"stream": true
|
|
187
|
+
}'
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
With tools:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
194
|
+
-H "Content-Type: application/json" \
|
|
195
|
+
-d '{
|
|
196
|
+
"model": "gpt-5.5",
|
|
197
|
+
"messages": [
|
|
198
|
+
{"role": "system", "content": "You have access to tools."},
|
|
199
|
+
{"role": "user", "content": "What is the weather in Seoul?"}
|
|
200
|
+
],
|
|
201
|
+
"tools": [
|
|
202
|
+
{
|
|
203
|
+
"type": "function",
|
|
204
|
+
"function": {
|
|
205
|
+
"name": "get_weather",
|
|
206
|
+
"description": "Get current weather",
|
|
207
|
+
"parameters": {
|
|
208
|
+
"type": "object",
|
|
209
|
+
"properties": {"city": {"type": "string"}},
|
|
210
|
+
"required": ["city"]
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
}'
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### `POST /v1/messages`
|
|
219
|
+
|
|
220
|
+
Anthropic Messages API compatible endpoint. Supports streaming (`stream: true`) and non-streaming. The client's model name is reflected in responses, but the server always uses the configured `CODEX_AS_API_MODEL` for the backend call.
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
curl http://localhost:18080/v1/messages \
|
|
224
|
+
-H "Content-Type: application/json" \
|
|
225
|
+
-H "x-api-key: unused" \
|
|
226
|
+
-H "anthropic-version: 2023-06-01" \
|
|
227
|
+
-d '{
|
|
228
|
+
"model": "claude-sonnet-4-6",
|
|
229
|
+
"max_tokens": 200,
|
|
230
|
+
"system": "You are a helpful assistant.",
|
|
231
|
+
"messages": [
|
|
232
|
+
{"role": "user", "content": "Hello!"}
|
|
233
|
+
]
|
|
234
|
+
}'
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Streaming:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
curl -N http://localhost:18080/v1/messages \
|
|
241
|
+
-H "Content-Type: application/json" \
|
|
242
|
+
-H "x-api-key: unused" \
|
|
243
|
+
-H "anthropic-version: 2023-06-01" \
|
|
244
|
+
-d '{
|
|
245
|
+
"model": "claude-sonnet-4-6",
|
|
246
|
+
"max_tokens": 200,
|
|
247
|
+
"stream": true,
|
|
248
|
+
"system": "You are a helpful assistant.",
|
|
249
|
+
"messages": [
|
|
250
|
+
{"role": "user", "content": "Hello!"}
|
|
251
|
+
]
|
|
252
|
+
}'
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### `POST /v1/images/generations`
|
|
256
|
+
|
|
257
|
+
Generate images via the Codex image generation tool.
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
curl http://localhost:18080/v1/images/generations \
|
|
261
|
+
-H "Content-Type: application/json" \
|
|
262
|
+
-d '{
|
|
263
|
+
"model": "gpt-5.5",
|
|
264
|
+
"prompt": "a futuristic city at sunset",
|
|
265
|
+
"size": "1024x1024"
|
|
266
|
+
}'
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### `POST /v1/inspect`
|
|
270
|
+
|
|
271
|
+
Inspect images with a text prompt (custom endpoint).
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
curl http://localhost:18080/v1/inspect \
|
|
275
|
+
-H "Content-Type: application/json" \
|
|
276
|
+
-d '{
|
|
277
|
+
"prompt": "Describe what you see",
|
|
278
|
+
"images": [{"image_url": "data:image/png;base64,iVBORw0KGgo..."}]
|
|
279
|
+
}'
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### `POST /v1/compact`
|
|
283
|
+
|
|
284
|
+
Compact a conversation into a checkpoint for continuation (custom endpoint).
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
curl http://localhost:18080/v1/compact \
|
|
288
|
+
-H "Content-Type: application/json" \
|
|
289
|
+
-d '{
|
|
290
|
+
"messages": [
|
|
291
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
292
|
+
{"role": "user", "content": "Summarize our conversation so far."},
|
|
293
|
+
{"role": "assistant", "content": "We discussed the project architecture."}
|
|
294
|
+
]
|
|
295
|
+
}'
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### `GET /health`
|
|
299
|
+
|
|
300
|
+
Health check. Returns auth availability and configured model.
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
curl http://localhost:18080/health
|
|
304
|
+
# {"status":"ok","auth_available":true,"model":"gpt-5.5"}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Codex-Specific Features
|
|
308
|
+
|
|
309
|
+
These features are extensions beyond the standard OpenAI API, designed for Codex CLI compatibility.
|
|
310
|
+
|
|
311
|
+
### `prompt_cache_key`
|
|
312
|
+
|
|
313
|
+
Enables prefix-cache stickiness on the Codex backend. When multiple requests share the same `prompt_cache_key`, the backend can reuse cached KV computations for the shared prefix, reducing latency and cost.
|
|
314
|
+
|
|
315
|
+
**When to use:** Set a stable key per conversation or session. All turns within the same session should share one key.
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
319
|
+
-H "Content-Type: application/json" \
|
|
320
|
+
-d '{
|
|
321
|
+
"model": "gpt-5.5",
|
|
322
|
+
"messages": [
|
|
323
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
324
|
+
{"role": "user", "content": "Hello"}
|
|
325
|
+
],
|
|
326
|
+
"prompt_cache_key": "session-abc-123"
|
|
327
|
+
}'
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### `reasoning_effort`
|
|
331
|
+
|
|
332
|
+
Controls how much compute the model spends on reasoning. Valid values: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`.
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
336
|
+
-H "Content-Type: application/json" \
|
|
337
|
+
-d '{
|
|
338
|
+
"model": "gpt-5.5",
|
|
339
|
+
"messages": [
|
|
340
|
+
{"role": "system", "content": "Solve this step by step."},
|
|
341
|
+
{"role": "user", "content": "Prove that sqrt(2) is irrational."}
|
|
342
|
+
],
|
|
343
|
+
"reasoning_effort": "high"
|
|
344
|
+
}'
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### `previous_response_id`
|
|
348
|
+
|
|
349
|
+
Chains responses together on the backend. Pass the response ID from a previous turn to maintain server-side conversation state.
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
353
|
+
-H "Content-Type: application/json" \
|
|
354
|
+
-d '{
|
|
355
|
+
"model": "gpt-5.5",
|
|
356
|
+
"messages": [
|
|
357
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
358
|
+
{"role": "user", "content": "Continue from where we left off."}
|
|
359
|
+
],
|
|
360
|
+
"previous_response_id": "resp_abc123"
|
|
361
|
+
}'
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### `subagent` / `x-openai-subagent`
|
|
365
|
+
|
|
366
|
+
Identifies the request as coming from a specific subagent type. Values used by Codex CLI: `review`, `compact`, `memory_consolidation`, `collab_spawn`.
|
|
367
|
+
|
|
368
|
+
Can be passed as a body field or HTTP header:
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
# As body field
|
|
372
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
373
|
+
-H "Content-Type: application/json" \
|
|
374
|
+
-d '{
|
|
375
|
+
"model": "gpt-5.5",
|
|
376
|
+
"messages": [{"role": "system", "content": "Review this code."}, {"role": "user", "content": "..."}],
|
|
377
|
+
"subagent": "review"
|
|
378
|
+
}'
|
|
379
|
+
|
|
380
|
+
# As HTTP header
|
|
381
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
382
|
+
-H "Content-Type: application/json" \
|
|
383
|
+
-H "x-openai-subagent: review" \
|
|
384
|
+
-d '{
|
|
385
|
+
"model": "gpt-5.5",
|
|
386
|
+
"messages": [{"role": "system", "content": "Review this code."}, {"role": "user", "content": "..."}]
|
|
387
|
+
}'
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### `memgen_request` / `x-openai-memgen-request`
|
|
391
|
+
|
|
392
|
+
Flags the request as a memory generation/consolidation request. Can be passed as a body field (`bool`) or HTTP header (`"true"/"false"`):
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
curl http://localhost:18080/v1/chat/completions \
|
|
396
|
+
-H "Content-Type: application/json" \
|
|
397
|
+
-H "x-openai-memgen-request: true" \
|
|
398
|
+
-d '{
|
|
399
|
+
"model": "gpt-5.5",
|
|
400
|
+
"messages": [{"role": "system", "content": "Consolidate memories."}, {"role": "user", "content": "..."}]
|
|
401
|
+
}'
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Using with OpenAI SDKs
|
|
405
|
+
|
|
406
|
+
Point the base URL to your local server:
|
|
407
|
+
|
|
408
|
+
### Python (openai SDK)
|
|
409
|
+
|
|
410
|
+
```python
|
|
411
|
+
from openai import OpenAI
|
|
412
|
+
|
|
413
|
+
client = OpenAI(
|
|
414
|
+
base_url="http://localhost:18080/v1",
|
|
415
|
+
api_key="unused",
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
response = client.chat.completions.create(
|
|
419
|
+
model="gpt-5.5",
|
|
420
|
+
messages=[
|
|
421
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
422
|
+
{"role": "user", "content": "Hello!"},
|
|
423
|
+
],
|
|
424
|
+
extra_body={"prompt_cache_key": "my-session"},
|
|
425
|
+
)
|
|
426
|
+
print(response.choices[0].message.content)
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Node.js (openai SDK)
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import OpenAI from "openai";
|
|
433
|
+
|
|
434
|
+
const client = new OpenAI({
|
|
435
|
+
baseURL: "http://localhost:18080/v1",
|
|
436
|
+
apiKey: "unused",
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
const response = await client.chat.completions.create({
|
|
440
|
+
model: "gpt-5.5",
|
|
441
|
+
messages: [
|
|
442
|
+
{ role: "system", content: "You are a helpful assistant." },
|
|
443
|
+
{ role: "user", content: "Hello!" },
|
|
444
|
+
],
|
|
445
|
+
});
|
|
446
|
+
console.log(response.choices[0].message.content);
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### curl (streaming)
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
curl -N http://localhost:18080/v1/chat/completions \
|
|
453
|
+
-H "Content-Type: application/json" \
|
|
454
|
+
-d '{
|
|
455
|
+
"model": "gpt-5.5",
|
|
456
|
+
"messages": [
|
|
457
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
458
|
+
{"role": "user", "content": "Tell me a joke."}
|
|
459
|
+
],
|
|
460
|
+
"stream": true,
|
|
461
|
+
"prompt_cache_key": "joke-session"
|
|
462
|
+
}'
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Using with Claude Code
|
|
466
|
+
|
|
467
|
+
The `/v1/messages` endpoint is compatible with [Claude Code](https://claude.ai/code). Claude Code sends the model name from its environment variables directly to the server, and the server passes it through to the Codex backend. You must set `ANTHROPIC_MODEL` (and per-role overrides) to a model the Codex backend supports (e.g., `gpt-5.5`).
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
# Minimal setup
|
|
471
|
+
ANTHROPIC_BASE_URL=http://localhost:18080 \
|
|
472
|
+
ANTHROPIC_API_KEY=unused \
|
|
473
|
+
ANTHROPIC_MODEL=gpt-5.5 \
|
|
474
|
+
claude
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# Full setup — override all roles so Claude Code never sends claude-* model names
|
|
479
|
+
ANTHROPIC_BASE_URL=http://localhost:18080 \
|
|
480
|
+
ANTHROPIC_API_KEY=unused \
|
|
481
|
+
ANTHROPIC_MODEL=gpt-5.5 \
|
|
482
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5.5 \
|
|
483
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-5.4 \
|
|
484
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5.4-mini \
|
|
485
|
+
CLAUDE_CODE_SUBAGENT_MODEL=gpt-5.4 \
|
|
486
|
+
claude
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
These are all Claude Code environment variables — they control what model name Claude Code sends in requests. The server passes the model name through to the Codex backend as-is.
|
|
490
|
+
|
|
491
|
+
## Architecture
|
|
492
|
+
|
|
493
|
+
```
|
|
494
|
+
Client (OpenAI SDK / curl)
|
|
495
|
+
|
|
|
496
|
+
v
|
|
497
|
+
HTTP Server (FastAPI / Axum / Express)
|
|
498
|
+
|
|
|
499
|
+
+---> ChatGPTOAuthProvider
|
|
500
|
+
|
|
|
501
|
+
+---> ~/.codex/auth.json (OAuth tokens, auto-refresh)
|
|
502
|
+
+---> https://chatgpt.com/backend-api/codex/responses
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
The provider handles:
|
|
506
|
+
- Token loading and automatic refresh on 401
|
|
507
|
+
- OpenAI Responses API over SSE
|
|
508
|
+
- `prompt_cache_key` passthrough for prefix-cache stickiness
|
|
509
|
+
- Reasoning content streaming (`reasoning_content`, `reasoning`)
|
|
510
|
+
- Tool call streaming
|
|
511
|
+
- Codex-specific headers (`x-openai-subagent`, `x-openai-memgen-request`)
|
|
512
|
+
- `previous_response_id` for response chaining
|
|
513
|
+
- Image generation and inspection
|
|
514
|
+
- Remote conversation compaction
|
|
515
|
+
|
|
516
|
+
## Tests
|
|
517
|
+
|
|
518
|
+
### Python
|
|
519
|
+
|
|
520
|
+
```bash
|
|
521
|
+
pip install -e ".[dev,server]"
|
|
522
|
+
pip install httpx
|
|
523
|
+
pytest tests/ -v
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
### Rust
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
cd rust
|
|
530
|
+
cargo test
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### TypeScript
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
cd ts
|
|
537
|
+
npm install
|
|
538
|
+
npm test
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
## License
|
|
542
|
+
|
|
543
|
+
Apache License 2.0 — derived from [OpenAI Codex CLI](https://github.com/openai/codex) (Apache-2.0, Copyright 2025 OpenAI).
|