codex-as-api 0.8.2__tar.gz → 0.9.2__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.
Files changed (52) hide show
  1. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/PKG-INFO +38 -25
  2. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/README.md +37 -24
  3. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/RELEASES.md +76 -0
  4. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/config/codex-upstream-contract.json +3 -3
  5. codex_as_api-0.9.2/config/verified-hidden-models.json +165 -0
  6. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/pyproject.toml +3 -1
  7. codex_as_api-0.9.2/scripts/check_no_static_model_catalog.py +413 -0
  8. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/__init__.py +1 -1
  9. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/anthropic_adapter.py +433 -20
  10. codex_as_api-0.9.2/src/codex_as_api/codex_version.py +558 -0
  11. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/messages.py +13 -0
  12. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/model_capabilities.py +71 -7
  13. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/provider.py +408 -73
  14. codex_as_api-0.9.2/src/codex_as_api/reasoning_signature.py +229 -0
  15. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/server.py +88 -63
  16. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/conftest.py +12 -1
  17. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_anthropic_adapter.py +915 -64
  18. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_auth.py +64 -32
  19. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_codex_config.py +15 -7
  20. codex_as_api-0.9.2/tests/test_codex_version.py +447 -0
  21. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_messages.py +44 -7
  22. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_model_capabilities.py +95 -38
  23. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_no_static_model_catalog.py +63 -0
  24. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_package_versions.py +8 -4
  25. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_protocol.py +18 -9
  26. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_provider.py +565 -87
  27. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_release_artifacts.py +14 -10
  28. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_rust_third_party_notices.py +8 -4
  29. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_server.py +859 -58
  30. codex_as_api-0.8.2/scripts/check_no_static_model_catalog.py +0 -202
  31. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/.gitignore +0 -0
  32. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/LICENSE +0 -0
  33. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/THIRD_PARTY_NOTICES.md +0 -0
  34. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/config/o200k_base.tiktoken +0 -0
  35. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/requirements.txt +0 -0
  36. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/rust/THIRD_PARTY_NOTICES.md +0 -0
  37. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/scripts/check_package_versions.py +0 -0
  38. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/scripts/check_registry_release.py +0 -0
  39. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/scripts/check_release_artifacts.py +0 -0
  40. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/scripts/generate_rust_third_party_notices.py +0 -0
  41. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/scripts/package_rust_release.py +0 -0
  42. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/auth.py +0 -0
  43. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/codex_config.py +0 -0
  44. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/o200k_tokenizer.py +0 -0
  45. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/protocol.py +0 -0
  46. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/src/codex_as_api/strict_json.py +0 -0
  47. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/__init__.py +0 -0
  48. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/fixtures/o200k_base_encode_ordinary.json +0 -0
  49. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_o200k_tokenizer.py +0 -0
  50. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_registry_release.py +0 -0
  51. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_strict_json.py +0 -0
  52. {codex_as_api-0.8.2 → codex_as_api-0.9.2}/tests/test_ultrafast.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codex-as-api
3
- Version: 0.8.2
3
+ Version: 0.9.2
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
@@ -192,9 +192,25 @@ model_auto_compact_token_limit = 244800
192
192
 
193
193
  ### Supported Models
194
194
 
195
- 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
+ Ordinary models and capabilities come from the authenticated Codex `/models` response. The proxy keeps each account/base-URL/client-version snapshot in memory for 300 seconds and invalidates it when a Responses `X-Models-Etag` changes. 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`. Model snapshots are never shared across accounts or served as an offline fallback.
196
196
 
197
- 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`.
197
+ Use `GET /v1/models` for the effective catalog. It includes exact slugs, visibility, `supported_in_api`, reasoning-summary controls, and opaque `comp_hash` compatibility identifiers when supplied. Unknown IDs return `404 model_not_found`. Automatic default selection uses only the upstream catalog's originally visible models, not the experimental additions below.
198
+
199
+ #### Experimental hidden models
200
+
201
+ These three upstream-hidden models returned real responses on October 24, 2026, and are explicitly included in codex-as-api's effective catalog:
202
+
203
+ | Model ID | Observed upstream purpose |
204
+ | --- | --- |
205
+ | `gpt-6-chat-thinking` | Server-described paid CCA experiment; hidden and marked unsupported in the upstream API catalog |
206
+ | `gpt-reserve` | Official Codex CLI's Luna Reserve routing for reserve usage |
207
+ | `codex-auto-review` | Official Codex CLI's Guardian automatic approval-review model |
208
+
209
+ A small authenticated smoke test also verified function-tool calling plus tool-result continuation for all three models, and executed a simple generated JavaScript function against four inputs per model. This is a basic functionality check, not a coding-quality benchmark.
210
+
211
+ **These are hidden models. Upstream support can stop at any time, and availability may differ by account. If a model stops responding, [open an issue](https://github.com/Eunho-J/codex-as-api/issues) with its model ID and a sanitized error; we will remove the discontinued model from this catalog.** Do not include access tokens or other credentials in the issue.
212
+
213
+ The proxy exposes these verified exceptions as selectable models and prefers their current live capability metadata. Bundled capability records keep only these three IDs available when a successful live catalog omits them; they do not bypass OAuth, upstream rejection, or a failed/malformed catalog fetch. A successful empty upstream catalog can therefore list these experimental entries, while health/default selection still fails until an ordinary upstream default is available. The proxy never selects a hidden experimental model as its automatic default.
198
214
 
199
215
  To use a different port:
200
216
 
@@ -284,11 +300,9 @@ it; continuation uses the complete provider Response items saved behind
284
300
 
285
301
  ### `POST /v1/messages`
286
302
 
287
- 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.
303
+ Anthropic Messages compatibility endpoint for any client, including Claude Code and Scheherazade. It supports streaming (`stream: true`) and non-streaming without a client-identification header. A live Codex model ID routes directly. A `claude-*` facade ID uses the configured Codex backend model, or the authenticated catalog default when no backend model is configured. Other unknown IDs fail. The response preserves the client-supplied model name.
288
304
 
289
- This compatibility endpoint is scoped to Claude Code requests. The proxy accepts
290
- and strips the non-forwarded `max_tokens` and `cache_control` compatibility
291
- fields only when one valid `x-claude-code-session-id` header is present.
305
+ `max_tokens` is a required positive compatibility hint: the private Codex OAuth transport does not expose a matching output-token cap. Valid ephemeral `cache_control` hints are accepted and stripped for every client; their TTL and breakpoint semantics are not forwarded. An optional `x-claude-code-session-id` provides stable hashed cache affinity, not permission to use the endpoint. `metadata.user_id` is accepted as client metadata and is not forwarded.
292
306
 
293
307
  ```bash
294
308
  curl http://localhost:18080/v1/messages \
@@ -325,7 +339,11 @@ curl -N http://localhost:18080/v1/messages \
325
339
  }'
326
340
  ```
327
341
 
328
- 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.
342
+ With `thinking.display: "summarized"` (the enabled/adaptive default), real Codex reasoning summaries are returned as Anthropic `thinking` blocks and streamed `thinking_delta` content, alongside the existing `codex_reasoning` / `codex_reasoning_delta` extensions. When upstream supplies encrypted reasoning, each reasoning item has its own proxy-specific `signature`: `codex-reasoning-v1:` followed by base64url JSON containing the format version, actual backend model ID, and original reasoning item ID, encrypted content and summary. This is an opaque continuation envelope, not an Anthropic cryptographic signature.
343
+
344
+ On the following assistant-history request, recognized envelopes restore the original Responses reasoning items before that assistant turn's text/tool calls. Historical signed reasoning is accepted even when the current call uses `thinking: {"type":"disabled"}`, including compaction calls: current output-generation settings do not invalidate prior reasoning input. Ciphertext is preserved unchanged; summary text is never converted to ordinary assistant speech. Missing or foreign signatures retain the legacy ignored-thinking behavior, while malformed recognized envelopes return HTTP 400. Reasoning is retained for the same backend model and across the verified `gpt-6.1-sol` / `gpt-6-astra` / `gpt-6-sol` / `gpt-6-luna` / `gpt-daybreak-blue-latest` combinations (25 authenticated source/target pairs); other cross-model envelopes are discarded while ordinary history remains.
345
+
346
+ Multiple summary parts share one thinking block per reasoning item. Encrypted-only items use an empty thinking string with a non-empty signature. Streaming sends `signature_delta` before the matching `content_block_stop`. `display: "omitted"` hides the summary but can preserve an encrypted-only signed block for continuity; disabled thinking suppresses thinking output. Items without encrypted content retain unsigned-summary compatibility behavior.
329
347
 
330
348
  Hosted Anthropic `web_search` declarations are rejected with HTTP 400 on
331
349
  Messages, token-counting, and compact requests. OpenAI Responses cannot supply
@@ -345,10 +363,7 @@ the completion is nonterminal or final usage is absent; a stream that has
345
363
  already started emits an Anthropic `error` event and never emits a successful
346
364
  `message_stop`. The final response includes every required usage field, using
347
365
  `null` only where the Anthropic type permits it, plus required container,
348
- citation, context-management, and direct-caller fields. To preserve Claude
349
- Code's realtime behavior, `message_start` is sent immediately without guessed
350
- input-token counts; this narrow stream-start shape is Claude Code compatibility
351
- behavior, not generic Anthropic API parity.
366
+ citation, context-management, and direct-caller fields. `message_start` is sent immediately with numeric zero counters in `message.usage`; these are provisional, not measured counts. The final `message_delta.usage` replaces them with authoritative cumulative totals, including disjoint cache buckets.
352
367
 
353
368
  Generated `tool_use` blocks with `caller: {"type":"direct"}` and empty
354
369
  assistant content arrays can be replayed through the request adapter. Malformed,
@@ -364,9 +379,9 @@ different jobs:
364
379
  | `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 |
365
380
  | `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 |
366
381
  | `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 |
367
- | `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 |
382
+ | `x-claude-code-session-id` | Not used | Optional cache-affinity header; its exact value supplies a hashed default key |
368
383
  | `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 |
369
- | `cache_control` | Not an OpenAI Chat control | Accepted only with the Claude Code session header, validated, then stripped before Codex transport |
384
+ | `cache_control` | Not an OpenAI Chat control | Accepted for every client, validated, then stripped before Codex transport |
370
385
 
371
386
  Anthropic `cache_control` is a cache-boundary annotation, not an identifier.
372
387
  This proxy accepts only `{"type":"ephemeral"}` with optional `ttl: "5m"` or
@@ -378,15 +393,13 @@ responses do not expose the Chat-only `response_id`. The custom
378
393
  `previous_response_id` support.
379
394
 
380
395
  The Anthropic type permits `cache_control: null`; the proxy treats that exact
381
- value as omission. A non-null cache-control object is validated in full and is
382
- accepted only on a Claude Code request.
396
+ value as omission. A non-null cache-control object is validated in full for every client.
383
397
 
384
398
  ### `POST /v1/messages/count_tokens`
385
399
 
386
- 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.
400
+ 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 `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.
387
401
 
388
- `max_tokens` and `cache_control` remain Claude Code-only compatibility hints on
389
- this route and require `x-claude-code-session-id` when present.
402
+ `max_tokens` and `cache_control` are optional client-neutral compatibility hints on this route; no Claude Code header is required.
390
403
 
391
404
  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`.
392
405
 
@@ -405,7 +418,7 @@ curl http://localhost:18080/v1/messages/count_tokens \
405
418
 
406
419
  ### `POST /v1/messages/compact`
407
420
 
408
- 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.
421
+ 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 valid `cache_control` hints are accepted for every client; the optional Claude Code session header only supplies cache affinity.
409
422
 
410
423
  ### `POST /v1/images/generations`
411
424
 
@@ -545,7 +558,7 @@ Requests can instead use the Responses-shaped effort/context object:
545
558
  - 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.
546
559
  - Remote compact keeps its existing private Codex `reasoning_effort` field but does not accept public `reasoning.mode` or `reasoning.context`.
547
560
 
548
- 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.
561
+ Anthropic `thinking` values map as `enabled → high` and `adaptive → medium`. Disabled thinking selects `none` when available, otherwise the lowest supported catalog effort, and suppresses reasoning output; it does not claim to eliminate a model's internal reasoning. `output_config.effort` takes precedence over adaptive or enabled thinking and supports `low`, `medium`, `high`, `xhigh`, and `max`. Call-level disabled thinking takes precedence over ambient `output_config.effort` for auxiliary calls such as WebFetch. Explicit unsupported effort requests still fail. Hosted Anthropic WebSearch is rejected 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.
549
562
 
550
563
  Anthropic's `JSONOutputFormat` carries a schema but no name. When Claude Code
551
564
  sends that official shape, the proxy follows pinned Codex 0.153.3 and supplies
@@ -587,7 +600,7 @@ unchanged. The proxy does not inherit speed defaults from Codex config.
587
600
 
588
601
  Official behavior reference: Codex [0.164.0 service-tier resolution](https://github.com/openai/codex/blob/rust-v0.164.0/codex-rs/tui/src/service_tier_resolution.rs)
589
602
  and [stable, enabled-by-default ultrafast feature](https://github.com/openai/codex/blob/rust-v0.164.0/codex-rs/features/src/lib.rs).
590
- The rest of the private HTTP contract remains pinned to 0.153.3.
603
+ The bundled private-protocol reference records the reviewed Codex source revision. Outbound client identity is separate: the proxy resolves the stable `latest` version of npm [`@openai/codex`](https://www.npmjs.com/package/@openai/codex) and uses that same version for the model-catalog `client_version` query and Codex User-Agent. It is not hardcoded to the bundled reference or inferred from a locally installed CLI. Successful version lookups are cached for one hour; a refresh failure retains the last successfully resolved version and retries after a short backoff. A cold lookup failure returns an explicit availability error rather than advertising an invented version.
591
604
 
592
605
  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).
593
606
 
@@ -819,9 +832,9 @@ ANTHROPIC_BASE_URL=http://127.0.0.1:18080 ANTHROPIC_AUTH_TOKEN=unused \
819
832
  claude --model gpt-5.6-luna --effort medium
820
833
  ```
821
834
 
822
- 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.
835
+ 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 use the configured Codex model or authenticated catalog default; the proxy preserves the selected client name in the Anthropic response.
823
836
 
824
- `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:
837
+ `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 or catalog-default 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:
825
838
 
826
839
  ```bash
827
840
  claude --model sonnet
@@ -831,7 +844,7 @@ If the gateway variables are already in `~/.claude/settings.json`, shell-level `
831
844
 
832
845
  Claude Code gateway discovery cannot expose raw `gpt-*` IDs because Claude Code filters discovered IDs to `claude*` and `anthropic*`. The official single custom-model option avoids a misleading facade ID. This integration is an Anthropic Messages-compatible bridge; Anthropic explicitly does not support routing Claude Code to non-Claude models through third-party gateways. See the official [model configuration](https://code.claude.com/docs/en/model-config), [gateway connection](https://code.claude.com/docs/en/llm-gateway-connect), and [gateway protocol](https://code.claude.com/docs/en/llm-gateway-protocol) references.
833
846
 
834
- The current bridge accepts Claude Code's exact no-op thinking cleanup (`clear_thinking_20251015` with `keep: "all"`). Context edits that would change history, task budgets, enabled beta tool fields such as `strict` or `defer_loading`, malformed output formats, and unsupported image source types return HTTP 400 because the Codex OAuth transport has no lossless equivalent. Valid base64 and URL image blocks plus `tool_result.is_error` are preserved during translation.
847
+ The bridge accepts Claude Code's no-op thinking cleanup (`clear_thinking_20251015` with `keep: "all"`), validates and ignores boolean `eager_input_streaming`, and accepts `defer_loading: false`. Context edits that would change history, task budgets, enabled strict/deferred tool execution, malformed output formats, and unsupported image source types return HTTP 400. Valid base64 and URL image blocks plus `tool_result.is_error` are preserved during translation.
835
848
 
836
849
  ## Architecture
837
850
 
@@ -158,9 +158,25 @@ model_auto_compact_token_limit = 244800
158
158
 
159
159
  ### Supported Models
160
160
 
161
- 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`.
161
+ Ordinary models and capabilities come from the authenticated Codex `/models` response. The proxy keeps each account/base-URL/client-version snapshot in memory for 300 seconds and invalidates it when a Responses `X-Models-Etag` changes. 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`. Model snapshots are never shared across accounts or served as an offline fallback.
162
162
 
163
- 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`.
163
+ Use `GET /v1/models` for the effective catalog. It includes exact slugs, visibility, `supported_in_api`, reasoning-summary controls, and opaque `comp_hash` compatibility identifiers when supplied. Unknown IDs return `404 model_not_found`. Automatic default selection uses only the upstream catalog's originally visible models, not the experimental additions below.
164
+
165
+ #### Experimental hidden models
166
+
167
+ These three upstream-hidden models returned real responses on October 24, 2026, and are explicitly included in codex-as-api's effective catalog:
168
+
169
+ | Model ID | Observed upstream purpose |
170
+ | --- | --- |
171
+ | `gpt-6-chat-thinking` | Server-described paid CCA experiment; hidden and marked unsupported in the upstream API catalog |
172
+ | `gpt-reserve` | Official Codex CLI's Luna Reserve routing for reserve usage |
173
+ | `codex-auto-review` | Official Codex CLI's Guardian automatic approval-review model |
174
+
175
+ A small authenticated smoke test also verified function-tool calling plus tool-result continuation for all three models, and executed a simple generated JavaScript function against four inputs per model. This is a basic functionality check, not a coding-quality benchmark.
176
+
177
+ **These are hidden models. Upstream support can stop at any time, and availability may differ by account. If a model stops responding, [open an issue](https://github.com/Eunho-J/codex-as-api/issues) with its model ID and a sanitized error; we will remove the discontinued model from this catalog.** Do not include access tokens or other credentials in the issue.
178
+
179
+ The proxy exposes these verified exceptions as selectable models and prefers their current live capability metadata. Bundled capability records keep only these three IDs available when a successful live catalog omits them; they do not bypass OAuth, upstream rejection, or a failed/malformed catalog fetch. A successful empty upstream catalog can therefore list these experimental entries, while health/default selection still fails until an ordinary upstream default is available. The proxy never selects a hidden experimental model as its automatic default.
164
180
 
165
181
  To use a different port:
166
182
 
@@ -250,11 +266,9 @@ it; continuation uses the complete provider Response items saved behind
250
266
 
251
267
  ### `POST /v1/messages`
252
268
 
253
- 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.
269
+ Anthropic Messages compatibility endpoint for any client, including Claude Code and Scheherazade. It supports streaming (`stream: true`) and non-streaming without a client-identification header. A live Codex model ID routes directly. A `claude-*` facade ID uses the configured Codex backend model, or the authenticated catalog default when no backend model is configured. Other unknown IDs fail. The response preserves the client-supplied model name.
254
270
 
255
- This compatibility endpoint is scoped to Claude Code requests. The proxy accepts
256
- and strips the non-forwarded `max_tokens` and `cache_control` compatibility
257
- fields only when one valid `x-claude-code-session-id` header is present.
271
+ `max_tokens` is a required positive compatibility hint: the private Codex OAuth transport does not expose a matching output-token cap. Valid ephemeral `cache_control` hints are accepted and stripped for every client; their TTL and breakpoint semantics are not forwarded. An optional `x-claude-code-session-id` provides stable hashed cache affinity, not permission to use the endpoint. `metadata.user_id` is accepted as client metadata and is not forwarded.
258
272
 
259
273
  ```bash
260
274
  curl http://localhost:18080/v1/messages \
@@ -291,7 +305,11 @@ curl -N http://localhost:18080/v1/messages \
291
305
  }'
292
306
  ```
293
307
 
294
- 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.
308
+ With `thinking.display: "summarized"` (the enabled/adaptive default), real Codex reasoning summaries are returned as Anthropic `thinking` blocks and streamed `thinking_delta` content, alongside the existing `codex_reasoning` / `codex_reasoning_delta` extensions. When upstream supplies encrypted reasoning, each reasoning item has its own proxy-specific `signature`: `codex-reasoning-v1:` followed by base64url JSON containing the format version, actual backend model ID, and original reasoning item ID, encrypted content and summary. This is an opaque continuation envelope, not an Anthropic cryptographic signature.
309
+
310
+ On the following assistant-history request, recognized envelopes restore the original Responses reasoning items before that assistant turn's text/tool calls. Historical signed reasoning is accepted even when the current call uses `thinking: {"type":"disabled"}`, including compaction calls: current output-generation settings do not invalidate prior reasoning input. Ciphertext is preserved unchanged; summary text is never converted to ordinary assistant speech. Missing or foreign signatures retain the legacy ignored-thinking behavior, while malformed recognized envelopes return HTTP 400. Reasoning is retained for the same backend model and across the verified `gpt-6.1-sol` / `gpt-6-astra` / `gpt-6-sol` / `gpt-6-luna` / `gpt-daybreak-blue-latest` combinations (25 authenticated source/target pairs); other cross-model envelopes are discarded while ordinary history remains.
311
+
312
+ Multiple summary parts share one thinking block per reasoning item. Encrypted-only items use an empty thinking string with a non-empty signature. Streaming sends `signature_delta` before the matching `content_block_stop`. `display: "omitted"` hides the summary but can preserve an encrypted-only signed block for continuity; disabled thinking suppresses thinking output. Items without encrypted content retain unsigned-summary compatibility behavior.
295
313
 
296
314
  Hosted Anthropic `web_search` declarations are rejected with HTTP 400 on
297
315
  Messages, token-counting, and compact requests. OpenAI Responses cannot supply
@@ -311,10 +329,7 @@ the completion is nonterminal or final usage is absent; a stream that has
311
329
  already started emits an Anthropic `error` event and never emits a successful
312
330
  `message_stop`. The final response includes every required usage field, using
313
331
  `null` only where the Anthropic type permits it, plus required container,
314
- citation, context-management, and direct-caller fields. To preserve Claude
315
- Code's realtime behavior, `message_start` is sent immediately without guessed
316
- input-token counts; this narrow stream-start shape is Claude Code compatibility
317
- behavior, not generic Anthropic API parity.
332
+ citation, context-management, and direct-caller fields. `message_start` is sent immediately with numeric zero counters in `message.usage`; these are provisional, not measured counts. The final `message_delta.usage` replaces them with authoritative cumulative totals, including disjoint cache buckets.
318
333
 
319
334
  Generated `tool_use` blocks with `caller: {"type":"direct"}` and empty
320
335
  assistant content arrays can be replayed through the request adapter. Malformed,
@@ -330,9 +345,9 @@ different jobs:
330
345
  | `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 |
331
346
  | `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 |
332
347
  | `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 |
333
- | `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 |
348
+ | `x-claude-code-session-id` | Not used | Optional cache-affinity header; its exact value supplies a hashed default key |
334
349
  | `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 |
335
- | `cache_control` | Not an OpenAI Chat control | Accepted only with the Claude Code session header, validated, then stripped before Codex transport |
350
+ | `cache_control` | Not an OpenAI Chat control | Accepted for every client, validated, then stripped before Codex transport |
336
351
 
337
352
  Anthropic `cache_control` is a cache-boundary annotation, not an identifier.
338
353
  This proxy accepts only `{"type":"ephemeral"}` with optional `ttl: "5m"` or
@@ -344,15 +359,13 @@ responses do not expose the Chat-only `response_id`. The custom
344
359
  `previous_response_id` support.
345
360
 
346
361
  The Anthropic type permits `cache_control: null`; the proxy treats that exact
347
- value as omission. A non-null cache-control object is validated in full and is
348
- accepted only on a Claude Code request.
362
+ value as omission. A non-null cache-control object is validated in full for every client.
349
363
 
350
364
  ### `POST /v1/messages/count_tokens`
351
365
 
352
- 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.
366
+ 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 `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.
353
367
 
354
- `max_tokens` and `cache_control` remain Claude Code-only compatibility hints on
355
- this route and require `x-claude-code-session-id` when present.
368
+ `max_tokens` and `cache_control` are optional client-neutral compatibility hints on this route; no Claude Code header is required.
356
369
 
357
370
  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`.
358
371
 
@@ -371,7 +384,7 @@ curl http://localhost:18080/v1/messages/count_tokens \
371
384
 
372
385
  ### `POST /v1/messages/compact`
373
386
 
374
- 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.
387
+ 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 valid `cache_control` hints are accepted for every client; the optional Claude Code session header only supplies cache affinity.
375
388
 
376
389
  ### `POST /v1/images/generations`
377
390
 
@@ -511,7 +524,7 @@ Requests can instead use the Responses-shaped effort/context object:
511
524
  - 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.
512
525
  - Remote compact keeps its existing private Codex `reasoning_effort` field but does not accept public `reasoning.mode` or `reasoning.context`.
513
526
 
514
- 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.
527
+ Anthropic `thinking` values map as `enabled → high` and `adaptive → medium`. Disabled thinking selects `none` when available, otherwise the lowest supported catalog effort, and suppresses reasoning output; it does not claim to eliminate a model's internal reasoning. `output_config.effort` takes precedence over adaptive or enabled thinking and supports `low`, `medium`, `high`, `xhigh`, and `max`. Call-level disabled thinking takes precedence over ambient `output_config.effort` for auxiliary calls such as WebFetch. Explicit unsupported effort requests still fail. Hosted Anthropic WebSearch is rejected 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.
515
528
 
516
529
  Anthropic's `JSONOutputFormat` carries a schema but no name. When Claude Code
517
530
  sends that official shape, the proxy follows pinned Codex 0.153.3 and supplies
@@ -553,7 +566,7 @@ unchanged. The proxy does not inherit speed defaults from Codex config.
553
566
 
554
567
  Official behavior reference: Codex [0.164.0 service-tier resolution](https://github.com/openai/codex/blob/rust-v0.164.0/codex-rs/tui/src/service_tier_resolution.rs)
555
568
  and [stable, enabled-by-default ultrafast feature](https://github.com/openai/codex/blob/rust-v0.164.0/codex-rs/features/src/lib.rs).
556
- The rest of the private HTTP contract remains pinned to 0.153.3.
569
+ The bundled private-protocol reference records the reviewed Codex source revision. Outbound client identity is separate: the proxy resolves the stable `latest` version of npm [`@openai/codex`](https://www.npmjs.com/package/@openai/codex) and uses that same version for the model-catalog `client_version` query and Codex User-Agent. It is not hardcoded to the bundled reference or inferred from a locally installed CLI. Successful version lookups are cached for one hour; a refresh failure retains the last successfully resolved version and retries after a short backoff. A cold lookup failure returns an explicit availability error rather than advertising an invented version.
557
570
 
558
571
  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).
559
572
 
@@ -785,9 +798,9 @@ ANTHROPIC_BASE_URL=http://127.0.0.1:18080 ANTHROPIC_AUTH_TOKEN=unused \
785
798
  claude --model gpt-5.6-luna --effort medium
786
799
  ```
787
800
 
788
- 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.
801
+ 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 use the configured Codex model or authenticated catalog default; the proxy preserves the selected client name in the Anthropic response.
789
802
 
790
- `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:
803
+ `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 or catalog-default 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:
791
804
 
792
805
  ```bash
793
806
  claude --model sonnet
@@ -797,7 +810,7 @@ If the gateway variables are already in `~/.claude/settings.json`, shell-level `
797
810
 
798
811
  Claude Code gateway discovery cannot expose raw `gpt-*` IDs because Claude Code filters discovered IDs to `claude*` and `anthropic*`. The official single custom-model option avoids a misleading facade ID. This integration is an Anthropic Messages-compatible bridge; Anthropic explicitly does not support routing Claude Code to non-Claude models through third-party gateways. See the official [model configuration](https://code.claude.com/docs/en/model-config), [gateway connection](https://code.claude.com/docs/en/llm-gateway-connect), and [gateway protocol](https://code.claude.com/docs/en/llm-gateway-protocol) references.
799
812
 
800
- The current bridge accepts Claude Code's exact no-op thinking cleanup (`clear_thinking_20251015` with `keep: "all"`). Context edits that would change history, task budgets, enabled beta tool fields such as `strict` or `defer_loading`, malformed output formats, and unsupported image source types return HTTP 400 because the Codex OAuth transport has no lossless equivalent. Valid base64 and URL image blocks plus `tool_result.is_error` are preserved during translation.
813
+ The bridge accepts Claude Code's no-op thinking cleanup (`clear_thinking_20251015` with `keep: "all"`), validates and ignores boolean `eager_input_streaming`, and accepts `defer_loading: false`. Context edits that would change history, task budgets, enabled strict/deferred tool execution, malformed output formats, and unsupported image source types return HTTP 400. Valid base64 and URL image blocks plus `tool_result.is_error` are preserved during translation.
801
814
 
802
815
  ## Architecture
803
816
 
@@ -1,5 +1,81 @@
1
1
  # Release Notes
2
2
 
3
+ ## v0.9.2
4
+
5
+ ### TypeScript version lookup deadline
6
+
7
+ - Keep the Codex version lookup timeout alive until the lookup settles, including
8
+ fetch implementations without active I/O handles. Clear the timer on completion.
9
+ - Fix Node 22 resolver timeout cancellation that blocked the v0.9.0 and v0.9.1
10
+ Release workflows. This release includes their reasoning and security updates.
11
+
12
+ ## v0.9.1
13
+
14
+ ### TypeScript dependency security updates
15
+
16
+ - Update Express to the 5.3 series and smol-toml to the 1.9.1 series.
17
+ - Refresh the lockfile to body-parser 2.4.0, proxy-addr 2.0.8 and qs 6.16.1,
18
+ addressing the reported request-parser, IP-trust and TOML-parser advisories.
19
+ - Keep Python, TypeScript and Rust package versions aligned. No API or reasoning
20
+ continuity behavior changes are included in this patch.
21
+
22
+ ## v0.9.0
23
+
24
+ ### Encrypted reasoning continuity
25
+
26
+ - Carry Codex reasoning items in a versioned proxy-specific `thinking.signature`
27
+ envelope and restore their opaque encrypted content on the following request.
28
+ The envelope is transport metadata, not a fabricated Anthropic signature.
29
+ - Preserve one thinking block per reasoning item, including multiple summary
30
+ parts and encrypted-only items. Streaming signatures precede their block stops;
31
+ signed reasoning history stays out of ordinary assistant text.
32
+ - Preserve reasoning across the verified GPT-6.1-Sol, GPT-6-Astra, GPT-6-Sol,
33
+ GPT-6-Luna and Daybreak Blue model combinations; authenticated replay passed
34
+ all 25 combinations. Daybreak availability remains account/authorization-gated.
35
+
36
+ ### Current client identity and experimental models
37
+
38
+ - Resolve outbound Codex client identity from npm `@openai/codex`'s stable latest
39
+ version instead of a hardcoded source-reference version. Use a consistent
40
+ version for model-catalog lookup and request headers, with bounded lookup,
41
+ in-memory caching and last-successful-version retry behavior.
42
+ - Explicitly include verified hidden models `gpt-6-chat-thinking`, `gpt-reserve`
43
+ and `codex-auto-review` in the effective catalog without choosing them as an
44
+ automatic default. Prefer current live capability metadata.
45
+ - Document their experimental status: upstream support may end at any time;
46
+ users should report a discontinued model in an issue so it can be removed.
47
+ Basic authenticated conversation, function-call continuation and generated-code
48
+ execution checks passed for all three.
49
+
50
+ ## v0.8.3
51
+
52
+ ### Client-neutral Anthropic compatibility (all runtimes)
53
+
54
+ - Remove Claude Code identity gates around valid required `max_tokens` and
55
+ ephemeral `cache_control` hints on Messages, counting and compact routes.
56
+ These are compatibility hints, not native Codex output caps or cache TTLs;
57
+ optional Claude session cache affinity remains available.
58
+ - Include provisional zero usage in every initial streaming `message_start`,
59
+ followed by authoritative final usage with the 0.8.2 disjoint cache accounting.
60
+ - Support summarized thinking as real unsigned thinking blocks/deltas, retaining
61
+ existing Codex reasoning extensions. Omitted and disabled thinking suppress
62
+ reasoning output; never fabricate an Anthropic signature.
63
+ - Resolve disabled-derived effort to the model's lowest supported level when
64
+ `none` is unavailable; explicit effort selection remains capability-checked.
65
+ - Validate and strip replayed assistant thinking history for multi-turn clients.
66
+ Accept standard `metadata.user_id` and boolean tool streaming hints without
67
+ inventing backend semantics, and use the live catalog default for unconfigured
68
+ `claude-*` facade routing.
69
+
70
+ ### Official test quality
71
+
72
+ - Replace regex diagnostic assertions with literal returned-error checks and
73
+ remove source-presence, filesystem-permission and worker-liveness oracles.
74
+ Retain actual input/output, persistence-content and cancellation-state cases.
75
+ - Repair stale client-gate expectations and positive controls, including valid
76
+ null cache hints, live-default Claude facade routing and mixed thinking/tool
77
+ replay. Validate all three runtimes with their standard regression runners.
78
+
3
79
  ## v0.8.2
4
80
 
5
81
  ### Hotfix: disjoint Anthropic cache usage (all runtimes)
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "upstream": {
3
3
  "repository": "openai/codex",
4
- "version": "0.153.3",
5
- "tag": "rust-v0.153.3",
6
- "commit": "b1a547b1f73ce86205d9222ac19cff334b3b7a2e"
4
+ "version": "0.164.0",
5
+ "tag": "rust-v0.164.0",
6
+ "commit": "6aaac694803004a63c6f393d153c96d22521a6b9"
7
7
  },
8
8
  "models_request": {
9
9
  "path": "/models",
@@ -0,0 +1,165 @@
1
+ {
2
+ "verified_at": "2026-10-23T21:33:21.486Z",
3
+ "warning": "Experimental hidden model; upstream support may stop at any time.",
4
+ "models": [
5
+ {
6
+ "slug": "gpt-6-chat-thinking",
7
+ "display_name": "GPT-6 Chat Thinking",
8
+ "description": "Experimental hidden model; upstream support may stop at any time.",
9
+ "priority": 2,
10
+ "visibility": "list",
11
+ "supported_in_api": true,
12
+ "default_reasoning_level": "medium",
13
+ "supported_reasoning_levels": [
14
+ {
15
+ "effort": "low",
16
+ "description": "Fast responses with lighter reasoning"
17
+ },
18
+ {
19
+ "effort": "medium",
20
+ "description": "Balances speed and reasoning depth for everyday tasks"
21
+ },
22
+ {
23
+ "effort": "high",
24
+ "description": "Greater reasoning depth for complex problems"
25
+ },
26
+ {
27
+ "effort": "xhigh",
28
+ "description": "Extra high reasoning depth for complex problems"
29
+ },
30
+ {
31
+ "effort": "max",
32
+ "description": "Maximum reasoning depth for the hardest problems"
33
+ }
34
+ ],
35
+ "multi_agent_reasoning_effort": null,
36
+ "supports_reasoning_summary_parameter": false,
37
+ "default_reasoning_summary": "none",
38
+ "comp_hash": "3000",
39
+ "context_window": 272000,
40
+ "max_context_window": 272000,
41
+ "auto_compact_token_limit": null,
42
+ "effective_context_window_percent": 95,
43
+ "input_modalities": [
44
+ "text",
45
+ "image"
46
+ ],
47
+ "service_tiers": [],
48
+ "default_service_tier": null,
49
+ "use_responses_lite": true,
50
+ "supports_image_detail_original": true,
51
+ "support_verbosity": false,
52
+ "default_verbosity": "medium"
53
+ },
54
+ {
55
+ "slug": "gpt-reserve",
56
+ "display_name": "GPT-Reserve",
57
+ "description": "Experimental hidden model; upstream support may stop at any time.",
58
+ "priority": 4,
59
+ "visibility": "list",
60
+ "supported_in_api": true,
61
+ "default_reasoning_level": "medium",
62
+ "supported_reasoning_levels": [
63
+ {
64
+ "effort": "low",
65
+ "description": "Fast responses with lighter reasoning"
66
+ },
67
+ {
68
+ "effort": "medium",
69
+ "description": "Balances speed and reasoning depth for everyday tasks"
70
+ },
71
+ {
72
+ "effort": "high",
73
+ "description": "Greater reasoning depth for complex problems"
74
+ },
75
+ {
76
+ "effort": "xhigh",
77
+ "description": "Extra high reasoning depth for complex problems"
78
+ },
79
+ {
80
+ "effort": "max",
81
+ "description": "Maximum reasoning depth for the hardest problems"
82
+ }
83
+ ],
84
+ "multi_agent_reasoning_effort": null,
85
+ "supports_reasoning_summary_parameter": true,
86
+ "default_reasoning_summary": "none",
87
+ "comp_hash": "3000",
88
+ "context_window": 272000,
89
+ "max_context_window": 872000,
90
+ "auto_compact_token_limit": null,
91
+ "effective_context_window_percent": 95,
92
+ "input_modalities": [
93
+ "text",
94
+ "image"
95
+ ],
96
+ "service_tiers": [
97
+ {
98
+ "id": "priority",
99
+ "name": "Fast",
100
+ "description": "1.5x speed, increased usage"
101
+ }
102
+ ],
103
+ "default_service_tier": null,
104
+ "use_responses_lite": true,
105
+ "supports_image_detail_original": true,
106
+ "support_verbosity": true,
107
+ "default_verbosity": "low"
108
+ },
109
+ {
110
+ "slug": "codex-auto-review",
111
+ "display_name": "Codex Auto Review",
112
+ "description": "Experimental hidden model; upstream support may stop at any time.",
113
+ "priority": 43,
114
+ "visibility": "list",
115
+ "supported_in_api": true,
116
+ "default_reasoning_level": "medium",
117
+ "supported_reasoning_levels": [
118
+ {
119
+ "effort": "low",
120
+ "description": "Fast responses with lighter reasoning"
121
+ },
122
+ {
123
+ "effort": "medium",
124
+ "description": "Balances speed and reasoning depth for everyday tasks"
125
+ },
126
+ {
127
+ "effort": "high",
128
+ "description": "Greater reasoning depth for complex problems"
129
+ },
130
+ {
131
+ "effort": "xhigh",
132
+ "description": "Extra high reasoning depth for complex problems"
133
+ },
134
+ {
135
+ "effort": "max",
136
+ "description": "Maximum reasoning depth for the hardest problems"
137
+ }
138
+ ],
139
+ "multi_agent_reasoning_effort": null,
140
+ "supports_reasoning_summary_parameter": true,
141
+ "default_reasoning_summary": "none",
142
+ "comp_hash": "3000",
143
+ "context_window": 272000,
144
+ "max_context_window": 872000,
145
+ "auto_compact_token_limit": null,
146
+ "effective_context_window_percent": 95,
147
+ "input_modalities": [
148
+ "text",
149
+ "image"
150
+ ],
151
+ "service_tiers": [
152
+ {
153
+ "id": "priority",
154
+ "name": "Fast",
155
+ "description": "1.5x speed, increased usage"
156
+ }
157
+ ],
158
+ "default_service_tier": null,
159
+ "use_responses_lite": true,
160
+ "supports_image_detail_original": true,
161
+ "support_verbosity": true,
162
+ "default_verbosity": "low"
163
+ }
164
+ ]
165
+ }