codex-as-api 0.6.5__tar.gz → 0.7.0__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.6.5 → codex_as_api-0.7.0}/.gitignore +1 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/PKG-INFO +164 -80
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/README.md +159 -74
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/RELEASES.md +72 -0
- codex_as_api-0.7.0/config/codex-upstream-contract.json +48 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/pyproject.toml +11 -7
- codex_as_api-0.7.0/requirements.txt +8 -0
- codex_as_api-0.7.0/rust/THIRD_PARTY_NOTICES.md +29069 -0
- codex_as_api-0.7.0/scripts/check_no_static_model_catalog.py +202 -0
- codex_as_api-0.7.0/scripts/check_package_versions.py +235 -0
- codex_as_api-0.7.0/scripts/check_registry_release.py +483 -0
- codex_as_api-0.7.0/scripts/check_release_artifacts.py +361 -0
- codex_as_api-0.7.0/scripts/generate_rust_third_party_notices.py +311 -0
- codex_as_api-0.7.0/scripts/package_rust_release.py +74 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/src/codex_as_api/__init__.py +1 -1
- codex_as_api-0.7.0/src/codex_as_api/anthropic_adapter.py +1084 -0
- codex_as_api-0.7.0/src/codex_as_api/auth.py +595 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/src/codex_as_api/codex_config.py +35 -14
- codex_as_api-0.7.0/src/codex_as_api/messages.py +172 -0
- codex_as_api-0.7.0/src/codex_as_api/model_capabilities.py +694 -0
- codex_as_api-0.7.0/src/codex_as_api/protocol.py +144 -0
- codex_as_api-0.7.0/src/codex_as_api/provider.py +2753 -0
- codex_as_api-0.7.0/src/codex_as_api/server.py +2639 -0
- codex_as_api-0.7.0/src/codex_as_api/strict_json.py +71 -0
- codex_as_api-0.7.0/tests/conftest.py +136 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/tests/test_anthropic_adapter.py +804 -169
- codex_as_api-0.7.0/tests/test_auth.py +1288 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/tests/test_codex_config.py +52 -11
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/tests/test_messages.py +40 -34
- codex_as_api-0.7.0/tests/test_model_capabilities.py +795 -0
- codex_as_api-0.7.0/tests/test_no_static_model_catalog.py +137 -0
- codex_as_api-0.7.0/tests/test_package_versions.py +155 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/tests/test_protocol.py +92 -28
- codex_as_api-0.7.0/tests/test_provider.py +4206 -0
- codex_as_api-0.7.0/tests/test_registry_release.py +501 -0
- codex_as_api-0.7.0/tests/test_release_artifacts.py +322 -0
- codex_as_api-0.7.0/tests/test_rust_third_party_notices.py +156 -0
- codex_as_api-0.7.0/tests/test_server.py +5893 -0
- codex_as_api-0.7.0/tests/test_strict_json.py +32 -0
- codex_as_api-0.6.5/config/codex-upstream-contract.json +0 -86
- codex_as_api-0.6.5/config/model-capabilities.json +0 -128
- codex_as_api-0.6.5/requirements-server.txt +0 -3
- codex_as_api-0.6.5/requirements.txt +0 -9
- codex_as_api-0.6.5/src/codex_as_api/anthropic_adapter.py +0 -938
- codex_as_api-0.6.5/src/codex_as_api/auth.py +0 -383
- codex_as_api-0.6.5/src/codex_as_api/messages.py +0 -121
- codex_as_api-0.6.5/src/codex_as_api/model_capabilities.py +0 -251
- codex_as_api-0.6.5/src/codex_as_api/protocol.py +0 -99
- codex_as_api-0.6.5/src/codex_as_api/provider.py +0 -1632
- codex_as_api-0.6.5/src/codex_as_api/server.py +0 -1335
- codex_as_api-0.6.5/tests/conftest.py +0 -54
- codex_as_api-0.6.5/tests/test_auth.py +0 -730
- codex_as_api-0.6.5/tests/test_model_capabilities.py +0 -104
- codex_as_api-0.6.5/tests/test_package_versions.py +0 -94
- codex_as_api-0.6.5/tests/test_provider.py +0 -1748
- codex_as_api-0.6.5/tests/test_server.py +0 -2692
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/LICENSE +0 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/THIRD_PARTY_NOTICES.md +0 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/config/o200k_base.tiktoken +0 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/src/codex_as_api/o200k_tokenizer.py +0 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/tests/__init__.py +0 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/tests/fixtures/o200k_base_encode_ordinary.json +0 -0
- {codex_as_api-0.6.5 → codex_as_api-0.7.0}/tests/test_o200k_tokenizer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: codex-as-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Use ChatGPT/Codex OAuth as a local OpenAI-compatible API server.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Eunho-J/codex-as-api
|
|
6
6
|
Project-URL: Repository, https://github.com/Eunho-J/codex-as-api
|
|
@@ -18,18 +18,17 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: fastapi>=0.100
|
|
22
|
+
Requires-Dist: pydantic>=2.0
|
|
21
23
|
Requires-Dist: regex
|
|
22
24
|
Requires-Dist: tomli>=2; python_version < '3.11'
|
|
25
|
+
Requires-Dist: uvicorn>=0.23
|
|
23
26
|
Provides-Extra: dev
|
|
24
27
|
Requires-Dist: httpx; extra == 'dev'
|
|
25
28
|
Requires-Dist: mypy; extra == 'dev'
|
|
26
29
|
Requires-Dist: pytest; extra == 'dev'
|
|
27
30
|
Requires-Dist: ruff; extra == 'dev'
|
|
28
31
|
Requires-Dist: types-regex; extra == 'dev'
|
|
29
|
-
Provides-Extra: server
|
|
30
|
-
Requires-Dist: fastapi>=0.100; extra == 'server'
|
|
31
|
-
Requires-Dist: pydantic>=2.0; extra == 'server'
|
|
32
|
-
Requires-Dist: uvicorn>=0.23; extra == 'server'
|
|
33
32
|
Description-Content-Type: text/markdown
|
|
34
33
|
|
|
35
34
|
# codex-as-api
|
|
@@ -43,16 +42,16 @@ Use ChatGPT / Codex OAuth as a local OpenAI-compatible API server.
|
|
|
43
42
|
|
|
44
43
|
## Features
|
|
45
44
|
|
|
46
|
-
- **OpenAI & Anthropic compatible** —
|
|
45
|
+
- **OpenAI & Anthropic compatible** — Chat Completions, Messages, and `GET /v1/models`
|
|
47
46
|
- **Claude Code ready** — use Codex models directly from Claude Code CLI
|
|
48
47
|
- **Streaming** — full SSE streaming for both OpenAI and Anthropic protocols
|
|
49
48
|
- **Tool calling** — function calls, tool results, and parallel tool calls
|
|
50
49
|
- **Image support** — generation, inspection, multimodal Chat input, and capability-gated `original` image detail in classic Responses
|
|
51
|
-
- **Reasoning** —
|
|
52
|
-
- **Codex features** — session-aware `prompt_cache_key`,
|
|
50
|
+
- **Reasoning** — capability-checked effort/context, persisted reasoning, and explicit Codex reasoning extensions without fabricated Anthropic signatures
|
|
51
|
+
- **Codex features** — live authenticated model discovery, session-aware `prompt_cache_key`, account-scoped Chat continuation, subagent headers, and remote compaction
|
|
53
52
|
- **Codex config aware** — reads `CODEX_HOME` / `~/.codex/config.toml` for model, reasoning-effort, and context-window settings
|
|
54
53
|
- **Token estimate & compaction helpers** — Anthropic-compatible `/v1/messages/count_tokens` and `/v1/messages/compact`
|
|
55
|
-
- **
|
|
54
|
+
- **Managed ChatGPT auth** — reads official `~/.codex/auth.json` token data and refreshes managed OAuth tokens
|
|
56
55
|
- **3 implementations** — Python, TypeScript (npm), and Rust — identical behavior
|
|
57
56
|
|
|
58
57
|
## What it does
|
|
@@ -70,9 +69,17 @@ npm install -g @openai/codex
|
|
|
70
69
|
codex login
|
|
71
70
|
```
|
|
72
71
|
|
|
73
|
-
The server reads
|
|
72
|
+
The server reads the official nested `tokens` object from that file and refreshes
|
|
73
|
+
managed ChatGPT OAuth tokens automatically. `auth_mode` may be omitted, `null`,
|
|
74
|
+
or `"chatgpt"`.
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
Unofficial root-level `access_token` / `refresh_token` / `id_token` fields and
|
|
77
|
+
noncanonical auth-mode aliases are rejected. The official
|
|
78
|
+
`"chatgptAuthTokens"` mode is also unsupported: those credentials are owned and
|
|
79
|
+
refreshed by an external host application, while this standalone proxy has no
|
|
80
|
+
host refresh callback. `personal_access_token`-, `agent_identity`-, and
|
|
81
|
+
Bedrock-only auth files are not ChatGPT OAuth credentials; run `codex login` to
|
|
82
|
+
create the supported managed-token file.
|
|
76
83
|
|
|
77
84
|
## Install & Run
|
|
78
85
|
|
|
@@ -97,7 +104,7 @@ Or from source:
|
|
|
97
104
|
```bash
|
|
98
105
|
git clone https://github.com/Eunho-J/codex-as-api.git
|
|
99
106
|
cd codex-as-api
|
|
100
|
-
pip install -e
|
|
107
|
+
pip install -e .
|
|
101
108
|
codex-as-api
|
|
102
109
|
```
|
|
103
110
|
|
|
@@ -139,7 +146,7 @@ Can also be used as a library:
|
|
|
139
146
|
import { ChatGPTOAuthProvider, createApp } from "codex-as-api";
|
|
140
147
|
|
|
141
148
|
// Use the provider directly
|
|
142
|
-
const provider = new ChatGPTOAuthProvider({ model: "gpt-5.
|
|
149
|
+
const provider = new ChatGPTOAuthProvider({ model: "gpt-5.6-sol" });
|
|
143
150
|
const response = await provider.chat(
|
|
144
151
|
[
|
|
145
152
|
{ role: "system", content: "You are helpful." },
|
|
@@ -163,9 +170,8 @@ Environment variables (Python, Rust, and TypeScript):
|
|
|
163
170
|
|----------|---------|-------------|
|
|
164
171
|
| `CODEX_AS_API_HOST` | `127.0.0.1` | Bind address |
|
|
165
172
|
| `CODEX_AS_API_PORT` | `18080` | Listen port |
|
|
166
|
-
| `CODEX_AS_API_MODEL` | `~/.codex/config.toml` `model`, else
|
|
173
|
+
| `CODEX_AS_API_MODEL` | `~/.codex/config.toml` `model`, else live default | Model identifier passed to Codex backend |
|
|
167
174
|
| `CODEX_AS_API_AUTH_PATH` | `~/.codex/auth.json` | Path to OAuth credentials file |
|
|
168
|
-
| `CODEX_AS_API_CODEX_CLI_VERSION` | `0.147.0` | Override the validated Codex compatibility baseline identified in backend request `User-Agent` headers |
|
|
169
175
|
| `CODEX_AS_API_RESPONSES_LITE` | `auto` | Responses Lite mode: `auto`, `on`, or `off` |
|
|
170
176
|
| `CODEX_AS_API_CODEX_METADATA` | `off` | Add Codex-style per-turn `client_metadata` and related backend headers |
|
|
171
177
|
| `CODEX_HOME` | `~/.codex` | Codex home directory used for `auth.json` and `config.toml` discovery |
|
|
@@ -176,29 +182,18 @@ The server also reads root-level Codex CLI settings from `~/.codex/config.toml`:
|
|
|
176
182
|
model = "gpt-5.6-sol"
|
|
177
183
|
model_reasoning_effort = "high"
|
|
178
184
|
|
|
179
|
-
# Optional
|
|
185
|
+
# Optional explicit context values. A published live maximum still clamps them.
|
|
180
186
|
model_context_window = 272000
|
|
181
187
|
model_auto_compact_token_limit = 244800
|
|
182
188
|
```
|
|
183
189
|
|
|
184
|
-
`CODEX_AS_API_MODEL` overrides the Codex config model.
|
|
190
|
+
`CODEX_AS_API_MODEL` overrides the Codex config model. Reasoning-effort precedence is request, Codex config, then the authenticated model catalog default when present. When no request or configured model exists, the proxy selects the catalog's first `visibility: "list"` model by ascending priority, matching Codex. The effective model, reasoning setting, catalog status, and context settings are exposed from `/health`; optional reasoning and context values are `null` when neither config nor the live catalog supplies them. Context settings are also returned by Anthropic token-count responses when available.
|
|
185
191
|
|
|
186
192
|
### Supported Models
|
|
187
193
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
| `gpt-5.6-sol` | Latest frontier agentic coding model; defaults to `low` effort in Codex |
|
|
192
|
-
| `gpt-5.6-terra` | Balanced agentic coding model for everyday work; defaults to `medium` effort |
|
|
193
|
-
| `gpt-5.6-luna` | Fast and affordable agentic coding model; defaults to `medium` effort |
|
|
194
|
-
| `gpt-5.5` | Frontier model for complex coding, research, and real-world work |
|
|
195
|
-
| `gpt-5.4` | Strong model for everyday coding |
|
|
196
|
-
| `gpt-5.4-mini` | Small, fast, and cost-efficient model for simpler coding tasks |
|
|
197
|
-
| `gpt-5.3-codex` | Coding-optimized model |
|
|
198
|
-
| `gpt-5.3-codex-spark` | Ultra-fast coding model |
|
|
199
|
-
| `gpt-5.2` | Previous generation model |
|
|
200
|
-
|
|
201
|
-
Model capability behavior is driven by `config/model-capabilities.json` across Python, TypeScript, and Rust. The public `gpt-5.6` alias uses Sol's private Codex capability entry. The GPT-5.6 entries use the official Codex Responses Lite contract and a 272,000-token **Codex OAuth** context-window maximum; do not substitute the larger public API context figures for this backend. Larger config overrides are clamped to 272,000. Unknown models use conservative behavior: classic Responses payloads, no assumed parallel tool support, no automatic verbosity, reasoning-effort, or service-tier fields, and, without config overrides, the legacy 200,000-token context / 160,000-token compact thresholds.
|
|
194
|
+
Models and capabilities come only from the authenticated Codex `/models` response. The proxy keeps each account/base-URL/client-version snapshot in memory for 300 seconds, invalidates it when a Responses `X-Models-Etag` changes, and never serves a static, stale, or cross-account fallback. An unavailable or malformed refresh returns `503 catalog_unavailable` before streaming headers are sent; an upstream HTTP rejection after the one allowed OAuth refresh preserves its status as `upstream_error`.
|
|
195
|
+
|
|
196
|
+
Use `GET /v1/models` instead of relying on a documentation list. Every row in the fresh authenticated snapshot is returned, including its exact slug, visibility, `supported_in_api`, reasoning-summary controls, and opaque `comp_hash` compatibility identifier when supplied. A valid empty catalog returns `200` with `data: []`; health and model-default resolution then return `503 catalog_unavailable` rather than selecting a fallback. Requests must use an exact live slug; unknown explicit IDs return `404 model_not_found`.
|
|
202
197
|
|
|
203
198
|
To use a different port:
|
|
204
199
|
|
|
@@ -214,6 +209,14 @@ CODEX_AS_API_HOST=0.0.0.0 codex-as-api
|
|
|
214
209
|
|
|
215
210
|
## API Endpoints
|
|
216
211
|
|
|
212
|
+
### `GET /v1/models`
|
|
213
|
+
|
|
214
|
+
Returns the current account's authenticated Codex model catalog using an OpenAI-compatible list envelope. The response includes safe routing and capability metadata but omits backend instructions and model messages.
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
curl http://localhost:18080/v1/models
|
|
218
|
+
```
|
|
219
|
+
|
|
217
220
|
### `POST /v1/chat/completions`
|
|
218
221
|
|
|
219
222
|
Standard OpenAI chat completions. Supports streaming (`stream: true`) and non-streaming.
|
|
@@ -273,15 +276,25 @@ curl http://localhost:18080/v1/chat/completions \
|
|
|
273
276
|
}'
|
|
274
277
|
```
|
|
275
278
|
|
|
279
|
+
`reasoning_content` is a response-only proxy extension. Chat request messages
|
|
280
|
+
cannot replay that field losslessly and reject it instead of silently dropping
|
|
281
|
+
it; continuation uses the complete provider Response items saved behind
|
|
282
|
+
`previous_response_id`.
|
|
283
|
+
|
|
276
284
|
### `POST /v1/messages`
|
|
277
285
|
|
|
278
|
-
Anthropic Messages
|
|
286
|
+
Claude Code compatibility endpoint using the Anthropic Messages shape. It supports streaming (`stream: true`) and non-streaming only for requests carrying one valid `x-claude-code-session-id` header. A live Codex model ID routes directly. A recognized `claude-*` facade ID requires an explicit `CODEX_AS_API_MODEL` or Codex config model that is present in the same fresh catalog; it is not silently routed to a default. Other unknown IDs fail. The response preserves the client-supplied model name.
|
|
287
|
+
|
|
288
|
+
This compatibility endpoint is scoped to Claude Code requests. The proxy accepts
|
|
289
|
+
and strips the non-forwarded `max_tokens` and `cache_control` compatibility
|
|
290
|
+
fields only when one valid `x-claude-code-session-id` header is present.
|
|
279
291
|
|
|
280
292
|
```bash
|
|
281
293
|
curl http://localhost:18080/v1/messages \
|
|
282
294
|
-H "Content-Type: application/json" \
|
|
283
295
|
-H "x-api-key: unused" \
|
|
284
296
|
-H "anthropic-version: 2023-06-01" \
|
|
297
|
+
-H "x-claude-code-session-id: example-session" \
|
|
285
298
|
-d '{
|
|
286
299
|
"model": "claude-sonnet-4-6",
|
|
287
300
|
"max_tokens": 200,
|
|
@@ -299,6 +312,7 @@ curl -N http://localhost:18080/v1/messages \
|
|
|
299
312
|
-H "Content-Type: application/json" \
|
|
300
313
|
-H "x-api-key: unused" \
|
|
301
314
|
-H "anthropic-version: 2023-06-01" \
|
|
315
|
+
-H "x-claude-code-session-id: example-session" \
|
|
302
316
|
-d '{
|
|
303
317
|
"model": "claude-sonnet-4-6",
|
|
304
318
|
"max_tokens": 200,
|
|
@@ -310,6 +324,35 @@ curl -N http://localhost:18080/v1/messages \
|
|
|
310
324
|
}'
|
|
311
325
|
```
|
|
312
326
|
|
|
327
|
+
Codex reasoning summaries are not Anthropic signed-thinking blocks. A non-streaming response exposes real upstream reasoning only through the top-level `codex_reasoning` proxy extension. A stream emits `event: codex_reasoning_delta` with `type: "codex_reasoning_delta"`. The proxy never fabricates `thinking`, `thinking_delta`, or `signature_delta` data.
|
|
328
|
+
|
|
329
|
+
Hosted Anthropic `web_search` declarations are rejected with HTTP 400 on
|
|
330
|
+
Messages, token-counting, and compact requests. OpenAI Responses cannot supply
|
|
331
|
+
the Anthropic server-tool provenance and encrypted lifecycle fields required to
|
|
332
|
+
translate a hosted result losslessly, so the gateway does not approximate that
|
|
333
|
+
protocol. Provider output containing an unexpected hosted web-search call is an
|
|
334
|
+
upstream protocol error instead of a fabricated Anthropic result block.
|
|
335
|
+
|
|
336
|
+
Completed responses require authoritative final token usage and a real
|
|
337
|
+
`response.completed` event. Emitted function calls map to `tool_calls` or
|
|
338
|
+
`tool_use`; otherwise a missing, `null`, or `true` `end_turn` maps to `stop` or
|
|
339
|
+
`end_turn`, matching pinned Codex, where only explicit `false` requests another
|
|
340
|
+
sampling turn. An explicit `false` completion without a representable client
|
|
341
|
+
tool call is an upstream protocol error because this proxy does not implement
|
|
342
|
+
Codex's internal follow-up loop. Non-streaming requests return HTTP 502 when
|
|
343
|
+
the completion is nonterminal or final usage is absent; a stream that has
|
|
344
|
+
already started emits an Anthropic `error` event and never emits a successful
|
|
345
|
+
`message_stop`. The final response includes every required usage field, using
|
|
346
|
+
`null` only where the Anthropic type permits it, plus required container,
|
|
347
|
+
citation, context-management, and direct-caller fields. To preserve Claude
|
|
348
|
+
Code's realtime behavior, `message_start` is sent immediately without guessed
|
|
349
|
+
input-token counts; this narrow stream-start shape is Claude Code compatibility
|
|
350
|
+
behavior, not generic Anthropic API parity.
|
|
351
|
+
|
|
352
|
+
Generated `tool_use` blocks with `caller: {"type":"direct"}` and empty
|
|
353
|
+
assistant content arrays can be replayed through the request adapter. Malformed,
|
|
354
|
+
null, or server-tool caller variants still fail before transport.
|
|
355
|
+
|
|
313
356
|
### Identifier and cache behavior
|
|
314
357
|
|
|
315
358
|
The two compatibility facades intentionally use the similarly named fields for
|
|
@@ -320,24 +363,31 @@ different jobs:
|
|
|
320
363
|
| `client_metadata.session_id` | Forwarded to Codex, used as the default `prompt_cache_key`, and required when Codex metadata mode is enabled | Not used or forwarded |
|
|
321
364
|
| `client_metadata.thread_id` | Codex metadata thread identity; defaults to `session_id` for a root request and preserves an explicit child thread | Not used or synthesized |
|
|
322
365
|
| `prompt_cache_key` | Explicit value wins; otherwise a non-empty `client_metadata.session_id` is used; otherwise omitted | Optional proxy extension; explicit value wins, otherwise the Claude Code session header is hashed |
|
|
323
|
-
| `x-claude-code-session-id` | Not used |
|
|
366
|
+
| `x-claude-code-session-id` | Not used | Required for the non-forwarded `max_tokens` and `cache_control` compatibility fields; its exact value also supplies hashed cache affinity |
|
|
324
367
|
| `previous_response_id` | Resolves a known entry from the 256-chain process-local history and replays full input/output over HTTP; never forwarded | Non-null values return Anthropic-style HTTP 400 because normal Messages is stateless |
|
|
325
|
-
| `cache_control` | Not an OpenAI Chat control |
|
|
368
|
+
| `cache_control` | Not an OpenAI Chat control | Accepted only with the Claude Code session header, validated, then stripped before Codex transport |
|
|
326
369
|
|
|
327
370
|
Anthropic `cache_control` is a cache-boundary annotation, not an identifier.
|
|
328
371
|
This proxy accepts only `{"type":"ephemeral"}` with optional `ttl: "5m"` or
|
|
329
|
-
`"1h"` at
|
|
372
|
+
`"1h"` at the top level and on supported system/content blocks and tools. The
|
|
330
373
|
private Codex request has no Anthropic breakpoint or TTL fields, so accepted
|
|
331
374
|
hints do not reproduce Anthropic caching semantics. Normal `/v1/messages`
|
|
332
375
|
responses do not expose the Chat-only `response_id`. The custom
|
|
333
376
|
`/v1/messages/compact` endpoint retains its documented local
|
|
334
377
|
`previous_response_id` support.
|
|
335
378
|
|
|
379
|
+
The Anthropic type permits `cache_control: null`; the proxy treats that exact
|
|
380
|
+
value as omission. A non-null cache-control object is validated in full and is
|
|
381
|
+
accepted only on a Claude Code request.
|
|
382
|
+
|
|
336
383
|
### `POST /v1/messages/count_tokens`
|
|
337
384
|
|
|
338
|
-
Anthropic-compatible token counting helper. Codex OAuth does not expose a count-only endpoint equivalent to Anthropic's native API, so this route counts text locally and returns context-window metadata for the effective backend model. Normalized model-visible messages, tool calls, tool-result metadata, reasoning, and tool schemas are counted once. Request-envelope and
|
|
385
|
+
Anthropic-compatible token counting helper. Codex OAuth does not expose a count-only endpoint equivalent to Anthropic's native API, so this route counts text locally and returns context-window metadata for the effective backend model. Normalized model-visible messages, tool calls, tool-result metadata, reasoning, and tool schemas are counted once. Request-envelope fields and the approved Claude Code `max_tokens` compatibility hint are excluded; other unsupported generation controls fail instead of becoming no-ops. Image inputs use a separate fixed estimate so inline base64 data is not counted as text.
|
|
339
386
|
|
|
340
|
-
|
|
387
|
+
`max_tokens` and `cache_control` remain Claude Code-only compatibility hints on
|
|
388
|
+
this route and require `x-claude-code-session-id` when present.
|
|
389
|
+
|
|
390
|
+
Text estimation uses a bundled port of official `tiktoken` `o200k_base` `encode_ordinary`: the same Unicode pre-tokenization regex, byte-pair merge algorithm, and merge-rank data are implemented in Python, TypeScript, and Rust. It is a local estimator, not model metadata and not a substitute for a provider count API. The project does not depend on a `tiktoken` package or download encoding data at runtime. The last upstream synchronization check was **2026-07-14**, against [`tiktoken` 0.13.0 at `08a5f3b`](https://github.com/openai/tiktoken/tree/08a5f3b2c987ada4fc5aa1f16c643c203fa8acaa); the bundled rank file SHA-256 is `446a9538cb6c348e3516120d7c08b09f57c36495e2acfffe59a5bf8b0cfb1a2d`.
|
|
341
391
|
|
|
342
392
|
Official Codex also has a [`ceil(UTF-8 bytes / 4)` truncation helper](https://github.com/openai/codex/blob/bd2de422aa287b97b06ca6425a10935bcf1b3731/codex-rs/utils/string/src/truncate.rs#L4-L84), but Codex documents the history estimate using that helper as [a coarse lower bound rather than a tokenizer-accurate count](https://github.com/openai/codex/blob/bd2de422aa287b97b06ca6425a10935bcf1b3731/codex-rs/core/src/context_manager/history.rs#L162-L186). This endpoint therefore uses exact `o200k_base` ordinary text tokenization instead. The complete request count remains an estimate because protocol-wrapper overhead and image cost are local constants, but the former byte-as-token and raw-payload double count that could overstate ordinary Claude Code requests by about 8x is removed.
|
|
343
393
|
|
|
@@ -354,7 +404,7 @@ curl http://localhost:18080/v1/messages/count_tokens \
|
|
|
354
404
|
|
|
355
405
|
### `POST /v1/messages/compact`
|
|
356
406
|
|
|
357
|
-
Anthropic-compatible alias for remote conversation compaction. Accepts Anthropic Messages-shaped bodies and returns compacted checkpoint content.
|
|
407
|
+
Anthropic-compatible alias for remote conversation compaction. Accepts Anthropic Messages-shaped bodies and returns compacted checkpoint content. Live GPT model IDs select the matching backend model, and Claude Code effort and Fast Mode controls use the same mappings as `/v1/messages`. Its required non-forwarded `max_tokens` and any `cache_control` hints require one valid `x-claude-code-session-id` header.
|
|
358
408
|
|
|
359
409
|
### `POST /v1/images/generations`
|
|
360
410
|
|
|
@@ -366,7 +416,7 @@ curl http://localhost:18080/v1/images/generations \
|
|
|
366
416
|
-d '{
|
|
367
417
|
"model": "gpt-5.5",
|
|
368
418
|
"prompt": "a futuristic city at sunset",
|
|
369
|
-
"size": "
|
|
419
|
+
"size": "auto"
|
|
370
420
|
}'
|
|
371
421
|
```
|
|
372
422
|
|
|
@@ -391,7 +441,7 @@ curl http://localhost:18080/v1/inspect \
|
|
|
391
441
|
|
|
392
442
|
Compact a conversation into a checkpoint for continuation (custom endpoint). `/v1/messages/compact` provides the Anthropic-compatible alias.
|
|
393
443
|
|
|
394
|
-
Compact accepts the existing private Codex `reasoning_effort` (or matching `reasoning.effort`) plus `prompt_cache_key`, supported `service_tier`, `text`, and top-level `verbosity`. A known process-local `previous_response_id` is resolved to its saved Response items and replayed as full compact input; the field is never forwarded to private Codex. Non-null caller-supplied `reasoning.mode` / `reasoning.context`, `prompt_cache_options`, cache breakpoints,
|
|
444
|
+
Compact accepts the existing private Codex `reasoning_effort` (or matching `reasoning.effort`) plus `prompt_cache_key`, supported `service_tier`, `text`, and top-level `verbosity`. A known process-local `previous_response_id` is resolved to its saved Response items and replayed as full compact input; the field is never forwarded to private Codex. Non-null caller-supplied `reasoning.mode` / `reasoning.context`, `prompt_cache_options`, cache breakpoints, encrypted-reasoning `include`, and deprecated `prompt_cache_retention` are rejected instead of being silently dropped; explicit `null` for those nullable compatibility controls is treated as omitted. Any supplied `safety_identifier`, including `null`, returns HTTP 400. When Responses Lite is active, the proxy follows the official private Codex builder and adds `reasoning.context: "all_turns"` on the compact wire.
|
|
395
445
|
|
|
396
446
|
```bash
|
|
397
447
|
curl http://localhost:18080/v1/compact \
|
|
@@ -407,11 +457,10 @@ curl http://localhost:18080/v1/compact \
|
|
|
407
457
|
|
|
408
458
|
### `GET /health`
|
|
409
459
|
|
|
410
|
-
|
|
460
|
+
Readiness check. It returns `200` only when OAuth is available, a fresh catalog can be loaded, and the effective model resolves. Optional catalog metadata is not a readiness requirement: `reasoning_effort`, `context_window`, and `auto_compact_token_limit` are `null` when the selected live row and explicit config do not provide them. Otherwise the route returns `503` with a typed, sanitized error instead of reporting a false healthy state. The payload exposes catalog timing and effective model settings, but never access tokens, account IDs, auth paths, upstream ETags, or upstream response bodies.
|
|
411
461
|
|
|
412
462
|
```bash
|
|
413
|
-
curl http://localhost:18080/health
|
|
414
|
-
# {"status":"ok","auth_available":true,"model":"gpt-5.6-sol","reasoning_effort":"high","codex_config_path":"/Users/me/.codex/config.toml","context_window":272000,"auto_compact_token_limit":244800}
|
|
463
|
+
curl -i http://localhost:18080/health
|
|
415
464
|
```
|
|
416
465
|
|
|
417
466
|
## Codex-Specific Features
|
|
@@ -422,7 +471,7 @@ These features are extensions beyond the standard OpenAI API, designed for Codex
|
|
|
422
471
|
|
|
423
472
|
`prompt_cache_key` keeps related prefixes in the same backend cache family. Use one stable, privacy-safe key per conversation or application prefix.
|
|
424
473
|
|
|
425
|
-
Official Codex 0.
|
|
474
|
+
Official Codex 0.153.3 [derives this field from Responses metadata](https://github.com/openai/codex/blob/b1a547b1f73ce86205d9222ac19cff334b3b7a2e/codex-rs/core/src/client.rs#L540-L550), unless an explicit override is present. This proxy follows the same precedence on Chat requests: explicit `prompt_cache_key`, then a non-empty `client_metadata.session_id`, then omission. It does not generate a process-wide session or reuse `thread_id` as the cache key.
|
|
426
475
|
|
|
427
476
|
The private Codex OAuth HTTP and WebSocket request structures do not contain public GPT-5.6 `prompt_cache_options` or content-block `prompt_cache_breakpoint` fields. This proxy treats explicit `null` as omitted and rejects non-null controls with HTTP 400 instead of forwarding a request that the private route rejects or silently pretending the requested cache policy was applied. Use a public Responses API client when explicit cache policy or breakpoints are required. See OpenAI's [public prompt caching guide](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-breakpoints).
|
|
428
477
|
|
|
@@ -441,9 +490,9 @@ GPT-5.6 cache accounting is returned, when the backend supplies it, as `usage.pr
|
|
|
441
490
|
|
|
442
491
|
### `reasoning_effort` and `reasoning`
|
|
443
492
|
|
|
444
|
-
The legacy top-level `reasoning_effort` remains supported.
|
|
493
|
+
The legacy top-level `reasoning_effort` remains supported. Every effort is checked against the selected live model. Codex's virtual `ultra` setting resolves to the model's advertised multi-agent effort when valid, otherwise `max` when supported, otherwise the model's highest advertised non-`ultra` effort. If no valid wire effort exists, the request fails instead of inventing one.
|
|
445
494
|
|
|
446
|
-
|
|
495
|
+
Requests can instead use the Responses-shaped effort/context object:
|
|
447
496
|
|
|
448
497
|
```json
|
|
449
498
|
{
|
|
@@ -453,49 +502,56 @@ GPT-5.6 requests can instead use the public Responses-shaped object:
|
|
|
453
502
|
{"role": "user", "content": "Find migration failure modes."}
|
|
454
503
|
],
|
|
455
504
|
"reasoning": {
|
|
456
|
-
"mode": "standard",
|
|
457
505
|
"effort": "high",
|
|
458
506
|
"context": "all_turns"
|
|
459
507
|
}
|
|
460
508
|
}
|
|
461
509
|
```
|
|
462
510
|
|
|
463
|
-
- `mode
|
|
464
|
-
- `mode: "pro"` returns HTTP 400. Official Codex has no private request field or alternate model/effort mapping for Pro. Codex `ultra` and `service_tier: "priority"` are different features.
|
|
511
|
+
- Non-null `mode`, including `"standard"` and `"pro"`, returns HTTP 400 because the private Codex request has no mode field or alternate model mapping. Codex `ultra` and `service_tier: "priority"` are different features.
|
|
465
512
|
- `context` is `auto`, `current_turn`, or `all_turns`. Encrypted reasoning content is included automatically on generation requests so full-history continuation can replay it.
|
|
466
513
|
- `reasoning_effort` and `reasoning.effort` may both be present only when equal. Conflicting values return HTTP 400.
|
|
467
514
|
- Responses Lite uses `all_turns` as the Codex wire default. An explicitly different context is rejected instead of silently overwritten; use `responses_lite: false` when the backend route supports classic Responses and another context is required.
|
|
468
515
|
- Remote compact keeps its existing private Codex `reasoning_effort` field but does not accept public `reasoning.mode` or `reasoning.context`.
|
|
469
516
|
|
|
470
|
-
Anthropic `thinking` values map as `enabled → high`, `adaptive → medium`, and `disabled → none`. Claude Code's `output_config.effort` takes precedence over adaptive or enabled thinking and supports `low`, `medium`, `high`, `xhigh`, and `max`. Call-level `thinking.disabled` takes precedence over ambient `output_config.effort
|
|
517
|
+
Anthropic `thinking` values map as `enabled → high`, `adaptive → medium`, and `disabled → none`. Claude Code's `output_config.effort` takes precedence over adaptive or enabled thinking and supports `low`, `medium`, `high`, `xhigh`, and `max`. Call-level `thinking.disabled` takes precedence over ambient `output_config.effort` for representable client-side auxiliary calls such as WebFetch; hosted Anthropic WebSearch is rejected before transport because its lifecycle cannot be translated losslessly. The supported reasoning context and verbosity extensions are also available on `/v1/messages`, image generation, and inspection requests; Pro, non-null public cache policy/breakpoints, and any supplied `safety_identifier` fail explicitly on the private Codex provider.
|
|
518
|
+
|
|
519
|
+
Anthropic's `JSONOutputFormat` carries a schema but no name. When Claude Code
|
|
520
|
+
sends that official shape, the proxy follows pinned Codex 0.153.3 and supplies
|
|
521
|
+
the transport-only name `codex_output_schema`; this label has no model-selection
|
|
522
|
+
or fallback role. An explicit proxy-extension name is preserved only when it is
|
|
523
|
+
already a valid Responses format name, and is never sanitized or truncated.
|
|
471
524
|
|
|
472
|
-
The pinned official Codex HTTP request has no `stop` field. Omitted
|
|
525
|
+
The pinned official Codex HTTP request has no `stop` field. Omitted OpenAI
|
|
526
|
+
`stop`, or explicit OpenAI `stop: null`, is omitted from the private request;
|
|
527
|
+
any other OpenAI `stop` value returns HTTP 400. Anthropic `stop_sequences`
|
|
528
|
+
follows its typed API contract: omission is allowed, while explicit `null` or
|
|
529
|
+
an array value returns HTTP 400 because the private transport cannot apply it.
|
|
473
530
|
|
|
474
531
|
The mapping is intentionally transport-aware:
|
|
475
532
|
|
|
476
533
|
| Public/facade input | Private Codex behavior |
|
|
477
534
|
|---|---|
|
|
478
|
-
| `reasoning.mode
|
|
479
|
-
| `reasoning.mode: "pro"` | HTTP 400; no official Codex alias |
|
|
535
|
+
| Non-null `reasoning.mode` | HTTP 400; no private Codex field or model alias |
|
|
480
536
|
| `prompt_cache_key` | Forward an explicit value; otherwise use non-empty `client_metadata.session_id` |
|
|
481
537
|
| Non-null `prompt_cache_options` / breakpoint | HTTP 400; `null` is omitted and there is no private field |
|
|
482
|
-
|
|
|
483
|
-
| Non-
|
|
538
|
+
| Any supplied `safety_identifier` | HTTP 400; the optional field is non-nullable and OAuth account/thread IDs are not semantic aliases |
|
|
539
|
+
| Non-null `stop` / `stop_sequences` | HTTP 400; no private field |
|
|
484
540
|
| `previous_response_id` | Resolve locally and replay complete Response history over HTTP |
|
|
485
541
|
| `service_tier: "fast"` | Send `service_tier: "priority"` |
|
|
486
542
|
| `service_tier: "default"` | Omit the field |
|
|
487
543
|
|
|
488
|
-
Authenticated tests on July 10, 2026 verified both official continuation paths with `gpt-5.6-sol`: a direct private Responses WebSocket completed a second delta request using the exact prior `response.id`, and the private HTTP endpoint completed the same continuation when the full prior input/output history was replayed. The proxy implements the HTTP replay strategy. Direct HTTP forwarding of `previous_response_id`, Pro, public cache controls, and `safety_identifier` was rejected and is not used. See OpenAI's [reasoning mode documentation](https://developers.openai.com/api/docs/guides/reasoning#reasoning-mode) and the Codex 0.
|
|
544
|
+
Authenticated tests on July 10, 2026 verified both official continuation paths with `gpt-5.6-sol`: a direct private Responses WebSocket completed a second delta request using the exact prior `response.id`, and the private HTTP endpoint completed the same continuation when the full prior input/output history was replayed. The proxy implements the HTTP replay strategy. Direct HTTP forwarding of `previous_response_id`, Pro, public cache controls, and `safety_identifier` was rejected and is not used. See OpenAI's [reasoning mode documentation](https://developers.openai.com/api/docs/guides/reasoning#reasoning-mode) and the Codex 0.153.3 [HTTP/WebSocket request structures](https://github.com/openai/codex/blob/b1a547b1f73ce86205d9222ac19cff334b3b7a2e/codex-rs/codex-api/src/common.rs#L275-L350).
|
|
489
545
|
|
|
490
546
|
### `responses_lite`
|
|
491
547
|
|
|
492
548
|
Controls the Codex Responses Lite request shape. Accepted values are `true`, `false`, and `"auto"`. Request value takes precedence over `CODEX_AS_API_RESPONSES_LITE`; default is `"auto"`.
|
|
493
549
|
|
|
494
|
-
In `"auto"` mode, this package
|
|
550
|
+
In `"auto"` mode, this package uses Lite only when the selected live catalog entry advertises it. Setting `responses_lite: true` forces the Lite request shape and moves tools/instructions into Lite-compatible developer input items.
|
|
495
551
|
|
|
496
552
|
Codex implements web search and image generation for Lite models through client-side standalone tools. This proxy has no standalone tool executor, so Lite requests containing hosted `web_search` or `image_generation` tools fail explicitly instead of silently dropping the tools. When a request does not override the mode, `CODEX_AS_API_RESPONSES_LITE=off` selects the existing classic request contract if the backend route supports it.
|
|
497
553
|
|
|
498
|
-
The official Codex Lite request builder
|
|
554
|
+
The official Codex Lite request builder has no lossless `input_image.detail` mapping. Classic Responses preserve `auto`, `low`, and `high`, plus `original` only when the live catalog advertises it. A caller-supplied image detail on Lite returns HTTP 400 instead of silently removing the requested behavior.
|
|
499
555
|
|
|
500
556
|
### Image detail
|
|
501
557
|
|
|
@@ -517,17 +573,17 @@ Chat multimodal blocks are preserved instead of being flattened to text:
|
|
|
517
573
|
}
|
|
518
574
|
```
|
|
519
575
|
|
|
520
|
-
`/v1/inspect` accepts the equivalent flat image object: `{"image_url":"data:image/...","detail":"original"}`. Recognized detail values are `auto`, `low`, `high`, and `original`; `original` additionally requires
|
|
576
|
+
`/v1/inspect` accepts the equivalent flat image object: `{"image_url":"data:image/...","detail":"original"}`. Recognized detail values are `auto`, `low`, `high`, and `original`; `original` additionally requires support in the live model catalog. See OpenAI's [image detail guide](https://developers.openai.com/api/docs/guides/images-vision#choose-an-image-detail-level).
|
|
521
577
|
|
|
522
578
|
### `safety_identifier` and verbosity
|
|
523
579
|
|
|
524
|
-
The public `safety_identifier` has no equivalent private Codex request field. `ChatGPT-Account-ID`, `thread-id`, and `session-id` identify different things and are not substituted.
|
|
580
|
+
The public `safety_identifier` has no equivalent private Codex request field. `ChatGPT-Account-ID`, `thread-id`, and `session-id` identify different things and are not substituted. Because this optional OpenAI field is non-nullable, any supplied value, including explicit `null`, returns HTTP 400.
|
|
525
581
|
|
|
526
582
|
Standard Chat `verbosity: "low" | "medium" | "high"` maps to Responses `text.verbosity`. The existing `text` extension remains supported. Supplying both is allowed only when the values agree.
|
|
527
583
|
|
|
528
584
|
### `parallel_tool_calls`
|
|
529
585
|
|
|
530
|
-
|
|
586
|
+
Classic Responses preserves an explicit `parallel_tool_calls` value without relying on a model-catalog capability that Codex does not define. Lite requests fail rather than silently disabling an explicit `true` value.
|
|
531
587
|
|
|
532
588
|
### `client_metadata` and `codex_metadata`
|
|
533
589
|
|
|
@@ -537,9 +593,9 @@ The installation ID and process window ID remain stable, while `turn_id` and `x-
|
|
|
537
593
|
|
|
538
594
|
### `previous_response_id`
|
|
539
595
|
|
|
540
|
-
Non-streaming responses and the final streaming finish chunk expose the real upstream Responses ID as `response_id`. The provider keeps up to 256 completed chains in a process-local LRU store. Passing a known ID as `previous_response_id` prepends the saved semantic input and exact prior `response.output_item.done` items
|
|
596
|
+
Non-streaming responses and the final streaming finish chunk expose the real upstream Responses ID as `response_id`. The provider keeps up to 256 completed chains in a process-local LRU store scoped to the authenticated account. Passing a known ID as `previous_response_id` under the same account prepends the saved semantic input and exact prior `response.output_item.done` items, including encrypted reasoning and tool items, then sends one full private HTTP request. When both the saved source model and current live model publish `comp_hash`, unequal values fail before sampling because automatic pre-turn compaction is not implemented; equal or unavailable hashes follow Codex's compatibility rule. The ID itself is never forwarded and is never converted to `thread_id`; another account cannot replay it.
|
|
541
597
|
|
|
542
|
-
That event source is intentional: the Codex 0.
|
|
598
|
+
That event source is intentional: the Codex 0.153.3 SSE parser [takes semantic items from `response.output_item.done`](https://github.com/openai/codex/blob/b1a547b1f73ce86205d9222ac19cff334b3b7a2e/codex-rs/codex-api/src/sse/responses.rs#L357-L372), while its [`response.completed` shape contains response metadata and usage](https://github.com/openai/codex/blob/b1a547b1f73ce86205d9222ac19cff334b3b7a2e/codex-rs/codex-api/src/sse/responses.rs#L118-L166), not replay history. The authenticated private HTTP rollout likewise returned an empty `response.completed.output`; the proxy therefore commits the completed output-item events instead of treating that extra field as conversation state.
|
|
543
599
|
|
|
544
600
|
Only a real `response.completed` event commits a chain. Branches from an older retained ID are supported. Restarting the server or evicting an old entry removes that local state; an unknown ID returns HTTP 400 before any upstream request.
|
|
545
601
|
|
|
@@ -667,15 +723,19 @@ curl -N http://localhost:18080/v1/chat/completions \
|
|
|
667
723
|
|
|
668
724
|
The `/v1/messages` endpoint implements the Anthropic Messages gateway shape used by Claude Code. The current request shape was reproduced with Claude Code `2.1.220`; streaming, real Codex OAuth chat, request-level GPT model routing, adaptive thinking, `--effort max`, and Fast Mode remain covered.
|
|
669
725
|
|
|
670
|
-
Start the proxy first. `CODEX_AS_API_MODEL` is
|
|
726
|
+
Start the proxy first. `CODEX_AS_API_MODEL` is required when Claude Code sends a built-in `claude-*` facade model name; the configured backend must exist in the fresh authenticated catalog:
|
|
671
727
|
|
|
672
728
|
```bash
|
|
673
729
|
CODEX_AS_API_MODEL=gpt-5.6-terra \
|
|
674
|
-
CODEX_AS_API_RESPONSES_LITE=off \
|
|
675
730
|
codex-as-api
|
|
676
731
|
```
|
|
677
732
|
|
|
678
|
-
|
|
733
|
+
Claude Code hosted WebSearch is not supported through this gateway, regardless
|
|
734
|
+
of Responses Lite mode. Classic Responses can execute an OpenAI hosted search,
|
|
735
|
+
but its output lacks the Anthropic provenance and encrypted lifecycle data
|
|
736
|
+
needed for a lossless Messages response. WebFetch remains a client-side
|
|
737
|
+
auxiliary request and retains the disabled-thinking precedence behavior when
|
|
738
|
+
process-level effort is enabled.
|
|
679
739
|
|
|
680
740
|
To keep the built-in Fable, Opus, Sonnet, and Haiku rows and append one GPT row, launch the GPT-routed Claude Code process with these variables:
|
|
681
741
|
|
|
@@ -702,7 +762,7 @@ If managed settings define an `availableModels` allowlist, that list must includ
|
|
|
702
762
|
|
|
703
763
|
For a persistent gateway configuration, put the same variables in the `env` object in `~/.claude/settings.json`. Do that only when every Claude Code process using that config should route through codex-as-api.
|
|
704
764
|
|
|
705
|
-
`ANTHROPIC_CUSTOM_MODEL_OPTION` adds one picker row. To make
|
|
765
|
+
`ANTHROPIC_CUSTOM_MODEL_OPTION` adds one picker row. To make another live model the visible GPT row, change that value and the display text. Any model returned by `/v1/models` can also be selected directly without changing the visible row:
|
|
706
766
|
|
|
707
767
|
```bash
|
|
708
768
|
ANTHROPIC_BASE_URL=http://127.0.0.1:18080 ANTHROPIC_AUTH_TOKEN=unused \
|
|
@@ -711,9 +771,9 @@ ANTHROPIC_BASE_URL=http://127.0.0.1:18080 ANTHROPIC_AUTH_TOKEN=unused \
|
|
|
711
771
|
claude --model gpt-5.6-luna --effort medium
|
|
712
772
|
```
|
|
713
773
|
|
|
714
|
-
|
|
774
|
+
Live Codex IDs are sent to the matching backend model. Built-in Claude/Fable/Opus/Sonnet/Haiku IDs are not Codex models, so recognized `claude-*` IDs require the explicitly configured `CODEX_AS_API_MODEL`; the proxy preserves the selected client name in the Anthropic response.
|
|
715
775
|
|
|
716
|
-
`ANTHROPIC_BASE_URL` applies to the whole Claude Code process. Therefore the built-in rows remain available in the picker, but they also pass through codex-as-api and use the configured Codex
|
|
776
|
+
`ANTHROPIC_BASE_URL` applies to the whole Claude Code process. Therefore the built-in rows remain available in the picker, but they also pass through codex-as-api and use the explicitly configured Codex backend; the rows do not call Anthropic models in that process. To use an actual Anthropic model and GPT in parallel, keep the gateway variables out of global settings, start the GPT process with the inline command above, and start a second process normally:
|
|
717
777
|
|
|
718
778
|
```bash
|
|
719
779
|
claude --model sonnet
|
|
@@ -735,19 +795,21 @@ HTTP Server (FastAPI / Axum / Express)
|
|
|
735
795
|
|
|
|
736
796
|
+---> ChatGPTOAuthProvider
|
|
737
797
|
|
|
|
738
|
-
+---> ~/.codex/auth.json (OAuth tokens, auto-refresh)
|
|
798
|
+
+---> ~/.codex/auth.json (managed ChatGPT OAuth tokens, auto-refresh)
|
|
799
|
+
+---> https://chatgpt.com/backend-api/codex/models
|
|
739
800
|
+---> https://chatgpt.com/backend-api/codex/responses
|
|
740
801
|
```
|
|
741
802
|
|
|
742
803
|
The provider handles:
|
|
743
|
-
-
|
|
804
|
+
- Managed ChatGPT token loading, proactive refresh five minutes before expiry, and refresh on 401
|
|
805
|
+
- Fresh-only authenticated model discovery, validation, and ETag invalidation
|
|
744
806
|
- OpenAI Responses API over SSE
|
|
745
807
|
- `prompt_cache_key` and cache read/write accounting
|
|
746
|
-
-
|
|
747
|
-
-
|
|
808
|
+
- Live catalog-gated reasoning effort and context handling
|
|
809
|
+
- Real Codex reasoning extensions without fabricated Anthropic signatures
|
|
748
810
|
- Tool call streaming
|
|
749
811
|
- Codex-specific headers (`x-openai-subagent`, `x-openai-memgen-request`)
|
|
750
|
-
- Bounded
|
|
812
|
+
- Bounded, account-scoped `previous_response_id` history replay over private HTTP
|
|
751
813
|
- Multimodal Chat input, image generation/inspection, and capability-gated classic `original` detail
|
|
752
814
|
- Remote conversation compaction
|
|
753
815
|
|
|
@@ -756,7 +818,10 @@ The provider handles:
|
|
|
756
818
|
The `Release` GitHub Actions workflow runs on a pushed `v*` tag. It rejects a
|
|
757
819
|
tag that does not exactly match every Python, npm, and Rust version surface,
|
|
758
820
|
runs the complete cross-runtime gate, and then publishes PyPI, npmjs, the
|
|
759
|
-
scoped GitHub npm package, platform Rust
|
|
821
|
+
scoped GitHub npm package, deterministic platform Rust ZIP archives, and one
|
|
822
|
+
GitHub Release. Each Rust archive contains the platform binary, `LICENSE`, and
|
|
823
|
+
the generated `THIRD_PARTY_NOTICES.md` covering both bundled tokenizer data and
|
|
824
|
+
the locked normal dependency graph across supported release targets.
|
|
760
825
|
|
|
761
826
|
The workflow uses registry-supported OIDC for PyPI and npmjs. No `PYPI_TOKEN`,
|
|
762
827
|
`NPM_TOKEN`, personal access token, or repository secret is required. One-time
|
|
@@ -776,9 +841,9 @@ registry setup is still required:
|
|
|
776
841
|
After bumping every version and passing the local gate, push the matching tag:
|
|
777
842
|
|
|
778
843
|
```bash
|
|
779
|
-
python scripts/check_package_versions.py --tag v0.
|
|
780
|
-
git tag v0.
|
|
781
|
-
git push origin v0.
|
|
844
|
+
python scripts/check_package_versions.py --tag v0.7.0
|
|
845
|
+
git tag v0.7.0
|
|
846
|
+
git push origin v0.7.0
|
|
782
847
|
```
|
|
783
848
|
|
|
784
849
|
## Tests
|
|
@@ -786,7 +851,7 @@ git push origin v0.6.5
|
|
|
786
851
|
### Python
|
|
787
852
|
|
|
788
853
|
```bash
|
|
789
|
-
pip install -e ".[dev
|
|
854
|
+
pip install -e ".[dev]"
|
|
790
855
|
pip install httpx
|
|
791
856
|
pytest tests/ -v
|
|
792
857
|
```
|
|
@@ -809,6 +874,25 @@ npm test
|
|
|
809
874
|
|
|
810
875
|
## Release Notes
|
|
811
876
|
|
|
877
|
+
### v0.7.0
|
|
878
|
+
|
|
879
|
+
- Replace bundled model capability tables with a fresh authenticated Codex
|
|
880
|
+
catalog and add `GET /v1/models` across all three runtimes.
|
|
881
|
+
- Remove stale/unknown-model fallbacks, fabricated Anthropic signatures, silent
|
|
882
|
+
request downgrades, and malformed upstream recovery; return typed failures.
|
|
883
|
+
- Reject hosted Anthropic WebSearch instead of translating incomplete OpenAI
|
|
884
|
+
search lifecycle data, and require authoritative completion and final usage.
|
|
885
|
+
- Keep immediate Claude Code `message_start` delivery without inventing token
|
|
886
|
+
counts; final Anthropic fields are emitted only from authoritative provider data.
|
|
887
|
+
- Scope continuation history and catalog state to the authenticated account,
|
|
888
|
+
validate before streaming, and make `/health` report actual readiness.
|
|
889
|
+
- Require the official nested `tokens` auth layout, remove root-level and
|
|
890
|
+
noncanonical auth aliases, and reject external-host `chatgptAuthTokens`.
|
|
891
|
+
- Pin the validated private contract to Codex `0.153.3` and publish the exact
|
|
892
|
+
tested artifacts to PyPI, npmjs, GitHub Packages, and GitHub Releases.
|
|
893
|
+
- Install Python server dependencies with the base package so the default
|
|
894
|
+
`pip install codex-as-api` command produces a runnable server.
|
|
895
|
+
|
|
812
896
|
### v0.6.5
|
|
813
897
|
|
|
814
898
|
- Align GPT-5.6 alias, Sol, Terra, and Luna context limits with Codex `0.147.0`
|