codex-as-api 0.6.1__tar.gz → 0.6.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 (33) hide show
  1. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/PKG-INFO +21 -5
  2. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/README.md +18 -4
  3. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/RELEASES.md +18 -0
  4. codex_as_api-0.6.2/THIRD_PARTY_NOTICES.md +34 -0
  5. codex_as_api-0.6.2/config/o200k_base.tiktoken +199998 -0
  6. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/pyproject.toml +7 -3
  7. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/requirements.txt +2 -0
  8. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/__init__.py +1 -1
  9. codex_as_api-0.6.2/src/codex_as_api/o200k_tokenizer.py +165 -0
  10. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/server.py +40 -24
  11. codex_as_api-0.6.2/tests/fixtures/o200k_base_encode_ordinary.json +46 -0
  12. codex_as_api-0.6.2/tests/test_o200k_tokenizer.py +33 -0
  13. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_server.py +105 -11
  14. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/.gitignore +0 -0
  15. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/LICENSE +0 -0
  16. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/config/model-capabilities.json +0 -0
  17. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/requirements-server.txt +0 -0
  18. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/anthropic_adapter.py +0 -0
  19. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/auth.py +0 -0
  20. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/codex_config.py +0 -0
  21. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/messages.py +0 -0
  22. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/model_capabilities.py +0 -0
  23. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/protocol.py +0 -0
  24. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/src/codex_as_api/provider.py +0 -0
  25. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/__init__.py +0 -0
  26. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/conftest.py +0 -0
  27. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_anthropic_adapter.py +0 -0
  28. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_auth.py +0 -0
  29. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_codex_config.py +0 -0
  30. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_messages.py +0 -0
  31. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_model_capabilities.py +0 -0
  32. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_protocol.py +0 -0
  33. {codex_as_api-0.6.1 → codex_as_api-0.6.2}/tests/test_provider.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-as-api
3
- Version: 0.6.1
3
+ Version: 0.6.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
@@ -18,12 +18,14 @@ 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: regex
21
22
  Requires-Dist: tomli>=2; python_version < '3.11'
22
23
  Provides-Extra: dev
23
24
  Requires-Dist: httpx; extra == 'dev'
24
25
  Requires-Dist: mypy; extra == 'dev'
25
26
  Requires-Dist: pytest; extra == 'dev'
26
27
  Requires-Dist: ruff; extra == 'dev'
28
+ Requires-Dist: types-regex; extra == 'dev'
27
29
  Provides-Extra: server
28
30
  Requires-Dist: fastapi>=0.100; extra == 'server'
29
31
  Requires-Dist: pydantic>=2.0; extra == 'server'
@@ -310,7 +312,11 @@ curl -N http://localhost:18080/v1/messages \
310
312
 
311
313
  ### `POST /v1/messages/count_tokens`
312
314
 
313
- Anthropic-compatible token counting helper. Codex OAuth does not expose a count-only endpoint equivalent to Anthropic's native API, so this route returns a conservative local estimate plus context-window metadata for the effective backend model. The estimate uses UTF-8 byte length as an upper bound for GPT/Codex BPE text tokens, then adds protocol overhead for roles, message boundaries, tools, raw request metadata, and images.
315
+ 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 generation-control fields are excluded, and image inputs use a separate fixed estimate so inline base64 data is not counted as text.
316
+
317
+ GPT-5-family text 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. Official `tiktoken` maps `gpt-5` and its `gpt-5-`-prefixed variants to [`o200k_base`](https://github.com/openai/tiktoken/blob/08a5f3b2c987ada4fc5aa1f16c643c203fa8acaa/tiktoken/model.py#L7-L20); this project applies that GPT-5-family encoding to the bundled `gpt-5.*` Codex model IDs. 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`.
318
+
319
+ Official Codex also has a [`ceil(UTF-8 bytes / 4)` truncation helper](https://github.com/openai/codex/blob/393f64565ab46f09d99ca4d9bd973537e72a114b/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/393f64565ab46f09d99ca4d9bd973537e72a114b/codex-rs/core/src/context_manager/history.rs#L160-L185). 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.
314
320
 
315
321
  ```bash
316
322
  curl http://localhost:18080/v1/messages/count_tokens \
@@ -636,7 +642,7 @@ curl -N http://localhost:18080/v1/chat/completions \
636
642
 
637
643
  ## Using with Claude Code
638
644
 
639
- The `/v1/messages` endpoint implements the Anthropic Messages gateway shape used by Claude Code. Compatibility was validated with Claude Code `2.1.208`, including streaming, a real `Read` tool loop, request-level GPT model routing, adaptive thinking, `--effort max`, and Fast Mode.
645
+ The `/v1/messages` endpoint implements the Anthropic Messages gateway shape used by Claude Code. Compatibility was validated with Claude Code `2.1.209`, including streaming, real Codex OAuth chat, request-level GPT model routing, adaptive thinking, `--effort max`, and Fast Mode.
640
646
 
641
647
  Start the proxy first. `CODEX_AS_API_MODEL` is the fallback used when Claude Code sends a built-in Anthropic model name:
642
648
 
@@ -656,7 +662,7 @@ CLAUDE_CODE_ATTRIBUTION_HEADER=0 \
656
662
  claude
657
663
  ```
658
664
 
659
- Run `/model` and select **GPT-5.6 Sol**. The custom entry is appended to the built-in rows rather than replacing them. Claude Code `2.1.208` recognizes this GPT model ID without a custom capability declaration: `/effort low|medium|high|xhigh|max`, the picker effort control, and `claude --effort ...` are translated from Claude Code's `output_config.effort` to the Codex reasoning effort. Claude Code Fast Mode's `speed: "fast"` is translated to the Codex `priority` service tier.
665
+ Run `/model` and select **GPT-5.6 Sol**. The custom entry is appended to the built-in rows rather than replacing them. Claude Code `2.1.209` recognizes this GPT model ID without a custom capability declaration: `/effort low|medium|high|xhigh|max`, the picker effort control, and `claude --effort ...` are translated from Claude Code's `output_config.effort` to the Codex reasoning effort. Claude Code Fast Mode's `speed: "fast"` is translated to the Codex `priority` service tier.
660
666
 
661
667
  If managed settings define an `availableModels` allowlist, that list must include the exact `ANTHROPIC_CUSTOM_MODEL_OPTION` value, such as `gpt-5.6-sol`; otherwise Claude Code hides or rejects the custom row.
662
668
 
@@ -714,7 +720,7 @@ The provider handles:
714
720
  ## Release & package publishing
715
721
 
716
722
  - Bump versions in `pyproject.toml`, `src/codex_as_api/__init__.py`, `src/codex_as_api/server.py`, `ts/package.json`, `ts/package-lock.json`, `rust/Cargo.toml`, and `rust/Cargo.lock`.
717
- - Publish a GitHub Release such as `v0.6.1` from the matching commit.
723
+ - Publish a GitHub Release such as `v0.6.2` from the matching commit.
718
724
  - The manually-dispatched `Publish npm packages` workflow builds/tests the TypeScript package, runs `npm pack --dry-run`, publishes `codex-as-api` to npmjs when `NPM_TOKEN` is configured, and publishes `@eunho-j/codex-as-api` to GitHub Packages with `GITHUB_TOKEN`.
719
725
 
720
726
  Publishing to npmjs requires an authenticated npm session (`npm login` beforehand; `npm whoami` should succeed). From the repository root, the publish itself is one command:
@@ -757,6 +763,16 @@ npm test
757
763
 
758
764
  ## Release Notes
759
765
 
766
+ ### v0.6.2
767
+
768
+ - Fix `/v1/messages/count_tokens` overcounting that could trigger Claude Code autocompaction on every turn.
769
+ - Count normalized model-visible messages, tool calls, reasoning, tool-result metadata, and tool schemas once; remove the second full raw-request-body addition.
770
+ - Port official `tiktoken` `o200k_base` ordinary encoding into Python, TypeScript, and Rust without adding a `tiktoken` package dependency or runtime rank download.
771
+ - Match the upstream Unicode text split and BPE merge ranks last checked on 2026-07-14 against `tiktoken` 0.13.0 at `08a5f3b`.
772
+ - Keep image input cost separate and count inline base64 images once rather than adding both a fixed image estimate and the base64 request bytes.
773
+ - Add matching Python, TypeScript, and Rust endpoint regressions: a 4,000-byte ASCII message now returns `1,012` instead of roughly `8,000`, and non-model control fields do not change the count.
774
+ - Validate the release with Claude Code `2.1.209` and real Codex OAuth chat.
775
+
760
776
  ### v0.6.1
761
777
 
762
778
  - Re-audit official Codex `0.144.4` and `main` at `393f64565ab46f09d99ca4d9bd973537e72a114b`, plus Claude Code `2.1.208`, before publishing.
@@ -278,7 +278,11 @@ curl -N http://localhost:18080/v1/messages \
278
278
 
279
279
  ### `POST /v1/messages/count_tokens`
280
280
 
281
- Anthropic-compatible token counting helper. Codex OAuth does not expose a count-only endpoint equivalent to Anthropic's native API, so this route returns a conservative local estimate plus context-window metadata for the effective backend model. The estimate uses UTF-8 byte length as an upper bound for GPT/Codex BPE text tokens, then adds protocol overhead for roles, message boundaries, tools, raw request metadata, and images.
281
+ 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 generation-control fields are excluded, and image inputs use a separate fixed estimate so inline base64 data is not counted as text.
282
+
283
+ GPT-5-family text 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. Official `tiktoken` maps `gpt-5` and its `gpt-5-`-prefixed variants to [`o200k_base`](https://github.com/openai/tiktoken/blob/08a5f3b2c987ada4fc5aa1f16c643c203fa8acaa/tiktoken/model.py#L7-L20); this project applies that GPT-5-family encoding to the bundled `gpt-5.*` Codex model IDs. 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`.
284
+
285
+ Official Codex also has a [`ceil(UTF-8 bytes / 4)` truncation helper](https://github.com/openai/codex/blob/393f64565ab46f09d99ca4d9bd973537e72a114b/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/393f64565ab46f09d99ca4d9bd973537e72a114b/codex-rs/core/src/context_manager/history.rs#L160-L185). 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.
282
286
 
283
287
  ```bash
284
288
  curl http://localhost:18080/v1/messages/count_tokens \
@@ -604,7 +608,7 @@ curl -N http://localhost:18080/v1/chat/completions \
604
608
 
605
609
  ## Using with Claude Code
606
610
 
607
- The `/v1/messages` endpoint implements the Anthropic Messages gateway shape used by Claude Code. Compatibility was validated with Claude Code `2.1.208`, including streaming, a real `Read` tool loop, request-level GPT model routing, adaptive thinking, `--effort max`, and Fast Mode.
611
+ The `/v1/messages` endpoint implements the Anthropic Messages gateway shape used by Claude Code. Compatibility was validated with Claude Code `2.1.209`, including streaming, real Codex OAuth chat, request-level GPT model routing, adaptive thinking, `--effort max`, and Fast Mode.
608
612
 
609
613
  Start the proxy first. `CODEX_AS_API_MODEL` is the fallback used when Claude Code sends a built-in Anthropic model name:
610
614
 
@@ -624,7 +628,7 @@ CLAUDE_CODE_ATTRIBUTION_HEADER=0 \
624
628
  claude
625
629
  ```
626
630
 
627
- Run `/model` and select **GPT-5.6 Sol**. The custom entry is appended to the built-in rows rather than replacing them. Claude Code `2.1.208` recognizes this GPT model ID without a custom capability declaration: `/effort low|medium|high|xhigh|max`, the picker effort control, and `claude --effort ...` are translated from Claude Code's `output_config.effort` to the Codex reasoning effort. Claude Code Fast Mode's `speed: "fast"` is translated to the Codex `priority` service tier.
631
+ Run `/model` and select **GPT-5.6 Sol**. The custom entry is appended to the built-in rows rather than replacing them. Claude Code `2.1.209` recognizes this GPT model ID without a custom capability declaration: `/effort low|medium|high|xhigh|max`, the picker effort control, and `claude --effort ...` are translated from Claude Code's `output_config.effort` to the Codex reasoning effort. Claude Code Fast Mode's `speed: "fast"` is translated to the Codex `priority` service tier.
628
632
 
629
633
  If managed settings define an `availableModels` allowlist, that list must include the exact `ANTHROPIC_CUSTOM_MODEL_OPTION` value, such as `gpt-5.6-sol`; otherwise Claude Code hides or rejects the custom row.
630
634
 
@@ -682,7 +686,7 @@ The provider handles:
682
686
  ## Release & package publishing
683
687
 
684
688
  - Bump versions in `pyproject.toml`, `src/codex_as_api/__init__.py`, `src/codex_as_api/server.py`, `ts/package.json`, `ts/package-lock.json`, `rust/Cargo.toml`, and `rust/Cargo.lock`.
685
- - Publish a GitHub Release such as `v0.6.1` from the matching commit.
689
+ - Publish a GitHub Release such as `v0.6.2` from the matching commit.
686
690
  - The manually-dispatched `Publish npm packages` workflow builds/tests the TypeScript package, runs `npm pack --dry-run`, publishes `codex-as-api` to npmjs when `NPM_TOKEN` is configured, and publishes `@eunho-j/codex-as-api` to GitHub Packages with `GITHUB_TOKEN`.
687
691
 
688
692
  Publishing to npmjs requires an authenticated npm session (`npm login` beforehand; `npm whoami` should succeed). From the repository root, the publish itself is one command:
@@ -725,6 +729,16 @@ npm test
725
729
 
726
730
  ## Release Notes
727
731
 
732
+ ### v0.6.2
733
+
734
+ - Fix `/v1/messages/count_tokens` overcounting that could trigger Claude Code autocompaction on every turn.
735
+ - Count normalized model-visible messages, tool calls, reasoning, tool-result metadata, and tool schemas once; remove the second full raw-request-body addition.
736
+ - Port official `tiktoken` `o200k_base` ordinary encoding into Python, TypeScript, and Rust without adding a `tiktoken` package dependency or runtime rank download.
737
+ - Match the upstream Unicode text split and BPE merge ranks last checked on 2026-07-14 against `tiktoken` 0.13.0 at `08a5f3b`.
738
+ - Keep image input cost separate and count inline base64 images once rather than adding both a fixed image estimate and the base64 request bytes.
739
+ - Add matching Python, TypeScript, and Rust endpoint regressions: a 4,000-byte ASCII message now returns `1,012` instead of roughly `8,000`, and non-model control fields do not change the count.
740
+ - Validate the release with Claude Code `2.1.209` and real Codex OAuth chat.
741
+
728
742
  ### v0.6.1
729
743
 
730
744
  - Re-audit official Codex `0.144.4` and `main` at `393f64565ab46f09d99ca4d9bd973537e72a114b`, plus Claude Code `2.1.208`, before publishing.
@@ -1,5 +1,23 @@
1
1
  # Release Notes
2
2
 
3
+ ## v0.6.2
4
+
5
+ ### Claude Code count_tokens autocompact fix
6
+
7
+ - Fix the Anthropic `/v1/messages/count_tokens` estimator treating every UTF-8 byte as a token and then adding the full raw request body a second time.
8
+ - Port official `tiktoken` `o200k_base` ordinary encoding into Python, TypeScript, and Rust: the same Unicode pre-tokenization regex, byte-pair merge algorithm, and merge ranks now count GPT-5-family text.
9
+ - Count tool calls, tool-result identifiers, reasoning content, and normalized tool schemas once while excluding model IDs, output limits, stream flags, metadata, and other non-model request controls.
10
+ - Keep the existing image estimate separate so URL and inline base64 images are counted once without tokenizing the base64 payload as text.
11
+ - Keep token counting local and OAuth-free. No `tiktoken` package dependency or first-run encoding download is introduced.
12
+ - Record the upstream synchronization point as `tiktoken` 0.13.0 commit `08a5f3b2c987ada4fc5aa1f16c643c203fa8acaa`, checked on 2026-07-14, with the official rank-file SHA-256 verified in packaged builds.
13
+
14
+ ### Validation
15
+
16
+ - A 4,000-byte ASCII message returns `1,012` input tokens in all three implementations instead of roughly `8,000`.
17
+ - Endpoint tests cover UTF-8 text, normalized tools, tool/reasoning history, URL and base64 images, ignored request controls, effective model limits, and zero upstream provider calls.
18
+ - Official `tiktoken` 0.13.0 token IDs match the bundled ports across reference vectors, randomized multilingual text, code, whitespace, contractions, special-token-shaped literals, and long single-piece input.
19
+ - Python, TypeScript, and Rust return identical counts across 204 cross-runtime endpoint cases; Claude Code 2.1.209 real Codex OAuth chat remains compatible.
20
+
3
21
  ## v0.6.1
4
22
 
5
23
  ### Claude Code 2.1.208 compatibility
@@ -0,0 +1,34 @@
1
+ # Third-Party Notices
2
+
3
+ ## OpenAI tiktoken
4
+
5
+ This project includes a port of the `o200k_base` ordinary-encoding logic and
6
+ the corresponding merge-rank data from
7
+ [openai/tiktoken](https://github.com/openai/tiktoken).
8
+
9
+ Synchronized with tiktoken 0.13.0 at commit
10
+ `08a5f3b2c987ada4fc5aa1f16c643c203fa8acaa` on 2026-07-14.
11
+ The bundled rank data has SHA-256
12
+ `446a9538cb6c348e3516120d7c08b09f57c36495e2acfffe59a5bf8b0cfb1a2d`.
13
+
14
+ MIT License
15
+
16
+ Copyright (c) 2022 OpenAI, Shantanu Jain
17
+
18
+ Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ of this software and associated documentation files (the "Software"), to deal
20
+ in the Software without restriction, including without limitation the rights
21
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
+ copies of the Software, and to permit persons to whom the Software is
23
+ furnished to do so, subject to the following conditions:
24
+
25
+ The above copyright notice and this permission notice shall be included in all
26
+ copies or substantial portions of the Software.
27
+
28
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34
+ SOFTWARE.