codex-as-api 0.7.0__tar.gz → 0.8.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.
Files changed (46) hide show
  1. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/PKG-INFO +49 -4
  2. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/README.md +48 -3
  3. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/RELEASES.md +25 -0
  4. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/pyproject.toml +1 -1
  5. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/__init__.py +1 -1
  6. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/server.py +1 -1
  7. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_provider.py +2 -2
  8. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/.gitignore +0 -0
  9. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/LICENSE +0 -0
  10. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/THIRD_PARTY_NOTICES.md +0 -0
  11. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/config/codex-upstream-contract.json +0 -0
  12. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/config/o200k_base.tiktoken +0 -0
  13. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/requirements.txt +0 -0
  14. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/rust/THIRD_PARTY_NOTICES.md +0 -0
  15. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/scripts/check_no_static_model_catalog.py +0 -0
  16. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/scripts/check_package_versions.py +0 -0
  17. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/scripts/check_registry_release.py +0 -0
  18. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/scripts/check_release_artifacts.py +0 -0
  19. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/scripts/generate_rust_third_party_notices.py +0 -0
  20. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/scripts/package_rust_release.py +0 -0
  21. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/anthropic_adapter.py +0 -0
  22. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/auth.py +0 -0
  23. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/codex_config.py +0 -0
  24. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/messages.py +0 -0
  25. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/model_capabilities.py +0 -0
  26. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/o200k_tokenizer.py +0 -0
  27. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/protocol.py +0 -0
  28. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/provider.py +0 -0
  29. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/src/codex_as_api/strict_json.py +0 -0
  30. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/__init__.py +0 -0
  31. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/conftest.py +0 -0
  32. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/fixtures/o200k_base_encode_ordinary.json +0 -0
  33. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_anthropic_adapter.py +0 -0
  34. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_auth.py +0 -0
  35. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_codex_config.py +0 -0
  36. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_messages.py +0 -0
  37. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_model_capabilities.py +0 -0
  38. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_no_static_model_catalog.py +0 -0
  39. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_o200k_tokenizer.py +0 -0
  40. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_package_versions.py +0 -0
  41. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_protocol.py +0 -0
  42. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_registry_release.py +0 -0
  43. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_release_artifacts.py +0 -0
  44. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_rust_third_party_notices.py +0 -0
  45. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_server.py +0 -0
  46. {codex_as_api-0.7.0 → codex_as_api-0.8.0}/tests/test_strict_json.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codex-as-api
3
- Version: 0.7.0
3
+ Version: 0.8.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
@@ -463,6 +463,36 @@ Readiness check. It returns `200` only when OAuth is available, a fresh catalog
463
463
  curl -i http://localhost:18080/health
464
464
  ```
465
465
 
466
+ ### `POST /v1/realtime/calls` (TypeScript)
467
+
468
+ Creates a ChatGPT Live (realtime voice) call on the OAuth-authenticated ChatGPT
469
+ backend. The client owns the media plane: it sends its own WebRTC SDP offer and
470
+ applies the returned answer, so no audio is relayed through this proxy.
471
+
472
+ The body is `{"sdp": "<offer>", "session": {...}}`. `session` may carry
473
+ `instructions`, a `voice` (default `cove`), and any additional ChatGPT Live
474
+ session field; `model` defaults to `gpt-live-1-codex`, and `delegation` defaults
475
+ to `{"type": "client"}`. The route rejects unknown top-level fields and any
476
+ client-chosen voice-session id (`id`, `session_id`, `voice_session_id`), because
477
+ the backend denies calls that set those itself. On success it returns `201` with
478
+ the SDP answer as `text/plain` and a mirror `Location: /v1/realtime/calls/{call_id}`.
479
+
480
+ ```bash
481
+ curl -i http://localhost:18080/v1/realtime/calls \
482
+ -H "Content-Type: application/json" \
483
+ -d '{"sdp": "v=0\r\n...", "session": {"instructions": "Reply briefly."}}'
484
+ ```
485
+
486
+ ### `WS /v1/realtime/sideband/{call_id}` (TypeScript)
487
+
488
+ Relays a WebSocket to the OpenAI realtime sideband of an already-created call
489
+ (`wss://api.openai.com/v1/live/{call_id}`) with the account's OAuth headers, so a
490
+ headless client — a bot, a server-side agent, or an observer attached to the same
491
+ call — can read and write realtime events without running the media plane.
492
+ Frames, text and binary, are forwarded verbatim; the proxy does not rewrite or
493
+ invent session events. Browser clients that already hold the `oai-events` data
494
+ channel do not need this route.
495
+
466
496
  ## Codex-Specific Features
467
497
 
468
498
  These features are extensions beyond the standard OpenAI API, designed for Codex CLI compatibility.
@@ -812,6 +842,7 @@ The provider handles:
812
842
  - Bounded, account-scoped `previous_response_id` history replay over private HTTP
813
843
  - Multimodal Chat input, image generation/inspection, and capability-gated classic `original` detail
814
844
  - Remote conversation compaction
845
+ - ChatGPT Live realtime call creation and a sideband event relay, in the TypeScript runtime only
815
846
 
816
847
  ## Release & package publishing
817
848
 
@@ -841,9 +872,9 @@ registry setup is still required:
841
872
  After bumping every version and passing the local gate, push the matching tag:
842
873
 
843
874
  ```bash
844
- python scripts/check_package_versions.py --tag v0.7.0
845
- git tag v0.7.0
846
- git push origin v0.7.0
875
+ python scripts/check_package_versions.py --tag v0.8.0
876
+ git tag v0.8.0
877
+ git push origin v0.8.0
847
878
  ```
848
879
 
849
880
  ## Tests
@@ -874,6 +905,20 @@ npm test
874
905
 
875
906
  ## Release Notes
876
907
 
908
+ ### v0.8.0
909
+
910
+ - Add ChatGPT Live realtime voice to the TypeScript runtime: `POST
911
+ /v1/realtime/calls` creates an OAuth-authorized call from a client-owned WebRTC
912
+ SDP offer and returns the SDP answer, and `WS /v1/realtime/sideband/{call_id}`
913
+ relays the OpenAI realtime event sideband for headless clients. Audio stays on
914
+ the client's media plane.
915
+ - Mirror the pinned Codex call contract exactly: one identity in
916
+ `x-session-id`/`session-id`/`thread-id`, the `openai-alpha: quicksilver=v2`
917
+ handshake, `intent=quicksilver&architecture=avas`, and a session payload that
918
+ never chooses its own voice-session id.
919
+ - Document realtime as a TypeScript-only capability; Python and Rust remain
920
+ HTTP-only in this release instead of claiming cross-runtime parity.
921
+
877
922
  ### v0.7.0
878
923
 
879
924
  - Replace bundled model capability tables with a fresh authenticated Codex
@@ -430,6 +430,36 @@ Readiness check. It returns `200` only when OAuth is available, a fresh catalog
430
430
  curl -i http://localhost:18080/health
431
431
  ```
432
432
 
433
+ ### `POST /v1/realtime/calls` (TypeScript)
434
+
435
+ Creates a ChatGPT Live (realtime voice) call on the OAuth-authenticated ChatGPT
436
+ backend. The client owns the media plane: it sends its own WebRTC SDP offer and
437
+ applies the returned answer, so no audio is relayed through this proxy.
438
+
439
+ The body is `{"sdp": "<offer>", "session": {...}}`. `session` may carry
440
+ `instructions`, a `voice` (default `cove`), and any additional ChatGPT Live
441
+ session field; `model` defaults to `gpt-live-1-codex`, and `delegation` defaults
442
+ to `{"type": "client"}`. The route rejects unknown top-level fields and any
443
+ client-chosen voice-session id (`id`, `session_id`, `voice_session_id`), because
444
+ the backend denies calls that set those itself. On success it returns `201` with
445
+ the SDP answer as `text/plain` and a mirror `Location: /v1/realtime/calls/{call_id}`.
446
+
447
+ ```bash
448
+ curl -i http://localhost:18080/v1/realtime/calls \
449
+ -H "Content-Type: application/json" \
450
+ -d '{"sdp": "v=0\r\n...", "session": {"instructions": "Reply briefly."}}'
451
+ ```
452
+
453
+ ### `WS /v1/realtime/sideband/{call_id}` (TypeScript)
454
+
455
+ Relays a WebSocket to the OpenAI realtime sideband of an already-created call
456
+ (`wss://api.openai.com/v1/live/{call_id}`) with the account's OAuth headers, so a
457
+ headless client — a bot, a server-side agent, or an observer attached to the same
458
+ call — can read and write realtime events without running the media plane.
459
+ Frames, text and binary, are forwarded verbatim; the proxy does not rewrite or
460
+ invent session events. Browser clients that already hold the `oai-events` data
461
+ channel do not need this route.
462
+
433
463
  ## Codex-Specific Features
434
464
 
435
465
  These features are extensions beyond the standard OpenAI API, designed for Codex CLI compatibility.
@@ -779,6 +809,7 @@ The provider handles:
779
809
  - Bounded, account-scoped `previous_response_id` history replay over private HTTP
780
810
  - Multimodal Chat input, image generation/inspection, and capability-gated classic `original` detail
781
811
  - Remote conversation compaction
812
+ - ChatGPT Live realtime call creation and a sideband event relay, in the TypeScript runtime only
782
813
 
783
814
  ## Release & package publishing
784
815
 
@@ -808,9 +839,9 @@ registry setup is still required:
808
839
  After bumping every version and passing the local gate, push the matching tag:
809
840
 
810
841
  ```bash
811
- python scripts/check_package_versions.py --tag v0.7.0
812
- git tag v0.7.0
813
- git push origin v0.7.0
842
+ python scripts/check_package_versions.py --tag v0.8.0
843
+ git tag v0.8.0
844
+ git push origin v0.8.0
814
845
  ```
815
846
 
816
847
  ## Tests
@@ -841,6 +872,20 @@ npm test
841
872
 
842
873
  ## Release Notes
843
874
 
875
+ ### v0.8.0
876
+
877
+ - Add ChatGPT Live realtime voice to the TypeScript runtime: `POST
878
+ /v1/realtime/calls` creates an OAuth-authorized call from a client-owned WebRTC
879
+ SDP offer and returns the SDP answer, and `WS /v1/realtime/sideband/{call_id}`
880
+ relays the OpenAI realtime event sideband for headless clients. Audio stays on
881
+ the client's media plane.
882
+ - Mirror the pinned Codex call contract exactly: one identity in
883
+ `x-session-id`/`session-id`/`thread-id`, the `openai-alpha: quicksilver=v2`
884
+ handshake, `intent=quicksilver&architecture=avas`, and a session payload that
885
+ never chooses its own voice-session id.
886
+ - Document realtime as a TypeScript-only capability; Python and Rust remain
887
+ HTTP-only in this release instead of claiming cross-runtime parity.
888
+
844
889
  ### v0.7.0
845
890
 
846
891
  - Replace bundled model capability tables with a fresh authenticated Codex
@@ -1,5 +1,30 @@
1
1
  # Release Notes
2
2
 
3
+ ## v0.8.0
4
+
5
+ ### ChatGPT Live realtime voice (TypeScript)
6
+
7
+ - Add `POST /v1/realtime/calls` to the TypeScript runtime. A client-owned WebRTC
8
+ SDP offer plus an optional `session` object (`instructions`, `voice`, ...) is
9
+ exchanged for the ChatGPT backend's SDP answer; the call id is returned both in
10
+ the mirrored `Location: /v1/realtime/calls/{call_id}` header and as
11
+ `x-realtime-call-id`, and the answer body is `text/plain`, never JSON.
12
+ - Add `WS /v1/realtime/sideband/{call_id}`, which relays text and binary realtime
13
+ frames to `wss://api.openai.com/v1/live/{call_id}` with the account's OAuth
14
+ headers so headless clients (bots, server-side agents, observers) can attach to
15
+ an existing call. The proxy does not proxy RTP; the media plane stays client-side.
16
+ - Send the exact call contract the backend authorizes for OAuth: `version`,
17
+ `openai-alpha: quicksilver=v2`, `session-id`/`x-session-id`/`thread-id` carrying
18
+ one minted identity, and `intent=quicksilver&architecture=avas`. Reject unknown
19
+ top-level request fields and any client-chosen voice-session id (`id`,
20
+ `session_id`, `voice_session_id`) instead of forwarding a call the backend
21
+ denies.
22
+ - Default `model` to `gpt-live-1-codex`, `voice` to `cove`, and `delegation` to
23
+ `{"type": "client"}`.
24
+ - Realtime is TypeScript-only in this release. The Python and Rust runtimes keep
25
+ their existing HTTP surface, and the runtime difference is stated in
26
+ `README.md` and `ts/README.md` rather than presented as parity.
27
+
3
28
  ## v0.7.0
4
29
 
5
30
  ### Live authenticated model catalog
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "codex-as-api"
7
- version = "0.7.0"
7
+ version = "0.8.0"
8
8
  description = "Use ChatGPT/Codex OAuth as a local OpenAI-compatible API server."
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -1,3 +1,3 @@
1
1
  """codex-as-api: Use ChatGPT/Codex OAuth as a local OpenAI-compatible API server."""
2
2
 
3
- __version__ = "0.7.0"
3
+ __version__ = "0.8.0"
@@ -497,7 +497,7 @@ def _health_error_message(exc: BaseException) -> str:
497
497
  app = FastAPI(
498
498
  title="codex-as-api",
499
499
  description="Local OpenAI-compatible API server backed by ChatGPT/Codex OAuth.",
500
- version="0.7.0",
500
+ version="0.8.0",
501
501
  )
502
502
 
503
503
 
@@ -2158,7 +2158,7 @@ def test_codex_cli_headers_include_official_originator_and_versioned_user_agent(
2158
2158
 
2159
2159
  assert headers["originator"] == "codex_cli_rs"
2160
2160
  assert headers["User-Agent"].startswith("codex_cli_rs/0.153.3 (")
2161
- assert headers["User-Agent"].endswith(") codex-as-api/0.7.0")
2161
+ assert headers["User-Agent"].endswith(") codex-as-api/0.8.0")
2162
2162
 
2163
2163
 
2164
2164
  def test_codex_cli_headers_reject_unpinned_version():
@@ -2881,7 +2881,7 @@ def test_provider_headers_include_codex_cli_headers(auth_json_factory):
2881
2881
 
2882
2882
  assert headers["originator"] == "codex_cli_rs"
2883
2883
  assert headers["User-Agent"].startswith("codex_cli_rs/0.153.3 (")
2884
- assert headers["User-Agent"].endswith(") codex-as-api/0.7.0")
2884
+ assert headers["User-Agent"].endswith(") codex-as-api/0.8.0")
2885
2885
  assert headers["Authorization"].startswith("Bearer ")
2886
2886
 
2887
2887
 
File without changes
File without changes