codex-backend-sdk 0.5.2__tar.gz → 0.5.4__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 (75) hide show
  1. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/CHANGELOG.md +25 -1
  2. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/PKG-INFO +39 -24
  3. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/README.md +34 -19
  4. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/__init__.py +9 -1
  5. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/_client.py +3 -2
  6. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/_models.py +26 -0
  7. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/_transport.py +21 -1
  8. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/codex_client.py +8 -0
  9. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/chatgpt_plugins.py +101 -19
  10. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/codex.py +213 -23
  11. codex_backend_sdk-0.5.4/codex_backend_sdk/resources/realtime.py +437 -0
  12. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/docs/api-reference.md +25 -1
  13. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/docs/backend-api.md +27 -13
  14. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/docs/desktop-endpoint-inventory.md +53 -7
  15. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/docs/endpoint-coverage.md +19 -8
  16. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/docs/openai-compatibility.md +9 -2
  17. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/pyproject.toml +5 -5
  18. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/conftest.py +2 -1
  19. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_basic.py +5 -2
  20. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_plugins.py +59 -13
  21. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_client_retry.py +19 -2
  22. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_codex_resources.py +148 -22
  23. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_openai_compatibility.py +36 -18
  24. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_realtime_resource.py +72 -0
  25. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/uv.lock +80 -28
  26. codex_backend_sdk-0.5.2/codex_backend_sdk/resources/realtime.py +0 -171
  27. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/.gitignore +0 -0
  28. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/LICENSE +0 -0
  29. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/_streaming.py +0 -0
  30. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/_utils.py +0 -0
  31. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/oauth.py +0 -0
  32. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/pkce.py +0 -0
  33. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/__init__.py +0 -0
  34. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/_responses_payloads.py +0 -0
  35. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/chatgpt.py +0 -0
  36. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/chatgpt_apps.py +0 -0
  37. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/chatgpt_connectors.py +0 -0
  38. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/chatgpt_plugin_bundles.py +0 -0
  39. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/chatgpt_plugin_shares.py +0 -0
  40. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/chatgpt_writing_blocks.py +0 -0
  41. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/codex_web_search.py +0 -0
  42. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/files.py +0 -0
  43. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/images.py +0 -0
  44. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/models.py +0 -0
  45. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/openai_oauth.py +0 -0
  46. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/remote_control.py +0 -0
  47. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/responses.py +0 -0
  48. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/responses_websocket.py +0 -0
  49. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/resources/worktree_snapshots.py +0 -0
  50. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/codex_backend_sdk/storage.py +0 -0
  51. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/examples/agent.py +0 -0
  52. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_account_info.py +0 -0
  53. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_apps.py +0 -0
  54. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_connectors.py +0 -0
  55. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_plugin_bundles.py +0 -0
  56. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_plugin_shares.py +0 -0
  57. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_projects_gizmos.py +0 -0
  58. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_resources.py +0 -0
  59. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_search_files.py +0 -0
  60. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_chatgpt_writing_blocks.py +0 -0
  61. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_codex_web_search.py +0 -0
  62. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_conversation.py +0 -0
  63. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_files_resource.py +0 -0
  64. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_hosted_mcp.py +0 -0
  65. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_images.py +0 -0
  66. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_oauth.py +0 -0
  67. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_openai_oauth_resources.py +0 -0
  68. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_prompt_cache_usage.py +0 -0
  69. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_reasoning.py +0 -0
  70. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_remote_control_resource.py +0 -0
  71. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_responses_resource.py +0 -0
  72. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_responses_websocket.py +0 -0
  73. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_structured_output.py +0 -0
  74. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_tools.py +0 -0
  75. {codex_backend_sdk-0.5.2 → codex_backend_sdk-0.5.4}/tests/test_worktree_snapshots.py +0 -0
@@ -2,7 +2,31 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## Unreleased
5
+ ## [0.5.4] - 2026-09-24
6
+
7
+ ### Fixed
8
+ - Preserve a bounded backend response body in raised HTTP errors so callers can
9
+ diagnose rejected requests without reconstructing the transport call.
10
+
11
+ ## [0.5.3] - 2026-09-18
12
+
13
+ ### Added
14
+ - Added the OpenAI-shaped `client.live.create(...)` and
15
+ `client.live.sideband.connect(...)` surfaces over the existing Codex OAuth
16
+ Realtime v3 transport, including the public response shape and lazy
17
+ sideband context-manager idiom.
18
+ - Added current Codex workspace usage, task-usage, turn-estimate, plugin/skill
19
+ analytics, and reset-credit history resources discovered by the refreshed
20
+ source scan.
21
+ - Added the current Desktop plugin home feed and explicit plugin/skill
22
+ enable-disable mutations.
23
+
24
+ ### Changed
25
+ - Updated the compatibility baseline to `openai-python` 3.16.1 while retaining
26
+ the additive low-level `client.realtime` API.
27
+ - Reconciled the endpoint inventory with the refreshed Codex and official
28
+ Desktop checkouts, and tightened validation of plugin catalog responses and
29
+ pagination state.
6
30
 
7
31
  ## [0.5.1] - 2026-08-14
8
32
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codex-backend-sdk
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary: Unofficial Python SDK for the ChatGPT Codex backend API
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -19,12 +19,12 @@ Requires-Dist: pydantic>=2.0
19
19
  Requires-Dist: requests>=2.28
20
20
  Requires-Dist: websocket-client>=1.8
21
21
  Provides-Extra: dev
22
- Requires-Dist: openai<2.53.0,>=1.0; (python_version < '3.10') and extra == 'dev'
23
- Requires-Dist: openai>=2.53.0; (python_version >= '3.10') and extra == 'dev'
22
+ Requires-Dist: openai<3.0,>=1.0; (python_version < '3.10') and extra == 'dev'
23
+ Requires-Dist: openai>=3.16.1; (python_version >= '3.10') and extra == 'dev'
24
24
  Requires-Dist: pytest>=7.0; extra == 'dev'
25
25
  Provides-Extra: openai
26
- Requires-Dist: openai<2.53.0,>=1.0; (python_version < '3.10') and extra == 'openai'
27
- Requires-Dist: openai>=2.53.0; (python_version >= '3.10') and extra == 'openai'
26
+ Requires-Dist: openai<3.0,>=1.0; (python_version < '3.10') and extra == 'openai'
27
+ Requires-Dist: openai>=3.16.1; (python_version >= '3.10') and extra == 'openai'
28
28
  Description-Content-Type: text/markdown
29
29
 
30
30
  # codex-backend-sdk
@@ -65,7 +65,7 @@ from codex_backend_sdk import OpenAI
65
65
  client = OpenAI().authenticate()
66
66
 
67
67
  response = client.responses.create(
68
- model="gpt-5.4",
68
+ model="gpt-5.5",
69
69
  input="Explain quicksort in one paragraph.",
70
70
  )
71
71
 
@@ -89,7 +89,8 @@ client.files # upload files for Apps/MCP parameters
89
89
  client.images # Codex-backed image generation and editing
90
90
  client.audio # ChatGPT-backed transcription
91
91
  client.embeddings # OpenAI embeddings endpoint through OAuth
92
- client.realtime # WebRTC call creation and Realtime connection headers
92
+ client.live # OpenAI-shaped GPT-Live creation and sideband attachment
93
+ client.realtime # additive low-level Codex Realtime v3 transport
93
94
  ```
94
95
 
95
96
  These resources follow `openai-python` conventions where the backend overlaps
@@ -142,7 +143,7 @@ dictionaries or raw streams when imposing a stable model would be misleading.
142
143
 
143
144
  ```python
144
145
  response = client.responses.create(
145
- model="gpt-5.4",
146
+ model="gpt-5.5",
146
147
  instructions="Be concise.",
147
148
  input="Summarize the CAP theorem.",
148
149
  reasoning={"effort": "medium", "summary": "auto"},
@@ -173,7 +174,7 @@ connection reusable across sequential turns:
173
174
 
174
175
  ```python
175
176
  with client.responses.websocket.connect() as ws:
176
- for event in ws.create({"model": "gpt-5.4", "input": "Say hello."}):
177
+ for event in ws.create({"model": "gpt-5.5", "input": "Say hello."}):
177
178
  if event.get("type") == "response.output_text.delta":
178
179
  print(event.get("delta", ""), end="")
179
180
  ```
@@ -197,7 +198,7 @@ print(client.responses.create(input=history).output_text)
197
198
 
198
199
  ```python
199
200
  compacted = client.responses.compact(
200
- model="gpt-5.4",
201
+ model="gpt-5.5",
201
202
  instructions="Preserve task-critical decisions and unresolved work.",
202
203
  input=history,
203
204
  )
@@ -268,7 +269,7 @@ print(result.output_parsed)
268
269
  for model in client.models.list():
269
270
  print(model.id, model.context_window, model.supported_reasoning_levels)
270
271
 
271
- model = client.models.retrieve("gpt-5.4")
272
+ model = client.models.retrieve("gpt-5.5")
272
273
  ```
273
274
 
274
275
  ### Upload a file
@@ -340,6 +341,10 @@ sports, and time commands. See the API reference for command validation.
340
341
  quota = client.codex.usage()
341
342
  daily = client.codex.usage_details.daily_token_breakdown()
342
343
  credits = client.codex.usage_details.credit_events()
344
+ plugin_metrics = client.codex.usage_details.plugin_usage_metrics(
345
+ start_date="2026-09-01",
346
+ end_date="2026-09-18",
347
+ )
343
348
 
344
349
  print(quota.get("rate_limit", {}).get("primary_window"))
345
350
  ```
@@ -443,6 +448,7 @@ tool annotations and own user confirmation; the SDK never auto-invokes tools.
443
448
  plugins = client.chatgpt.plugins.list_all(scope="GLOBAL")
444
449
  installed = client.chatgpt.plugins.installed_all()
445
450
  suggested = client.chatgpt.plugins.suggested()
451
+ home = client.chatgpt.plugins.home()
446
452
  skill = client.chatgpt.plugins.skill("plugins~...", "skill-name")
447
453
 
448
454
  checkout = client.chatgpt.plugins.bundles.extract_plugin(
@@ -491,33 +497,42 @@ return a typed in-memory object, bytes, `BytesIO`, a data URI, or a file path.
491
497
  ### Realtime voice
492
498
 
493
499
  ```python
494
- answer = client.realtime.calls.create_v3(
495
- sdp=offer_sdp,
500
+ live = client.live.create(
496
501
  session={
497
502
  "model": "gpt-live-1-codex",
498
503
  "instructions": "Speak naturally and stay concise.",
504
+ "delegation": {"type": "client"},
499
505
  },
506
+ transport={"type": "webrtc", "sdp": offer_sdp},
500
507
  )
501
- print(answer.answer_sdp)
508
+ apply_remote_sdp(live.transport.sdp)
509
+
510
+ with client.live.sideband.connect(session_id=live.session.id) as sideband:
511
+ for event in sideband:
512
+ print(event.type)
502
513
  ```
503
514
 
504
515
  Live probes confirmed `gpt-live-1-codex` and
505
516
  `gpt-live-1-boulder-alpha`. They are Codex Realtime v3 snapshots, not aliases
506
- for the public `gpt-realtime` family. The call response exposes `call_id`; join
507
- its OAuth-authenticated control and delegation channel with:
517
+ for the public `gpt-live-1` model. `client.live` follows the current
518
+ `openai-python` creation, response, and sideband idioms while adapting them to
519
+ the ChatGPT OAuth call transport.
520
+
521
+ The earlier low-level surface remains available for backend-specific code:
508
522
 
509
523
  ```python
510
- sideband = client.realtime.sideband.connect(
511
- call_id=answer.call_id,
512
- session_id="voice-session",
524
+ answer = client.realtime.calls.create_v3(
525
+ sdp=offer_sdp,
526
+ session={"model": "gpt-live-1-codex"},
513
527
  )
514
- sideband.send({"type": "delegation.context.append", "content": []})
515
- event = sideband.recv()
516
- sideband.close()
528
+ with client.realtime.sideband.connect(call_id=answer.call_id) as sideband:
529
+ sideband.send({"type": "session.close"})
517
530
  ```
518
531
 
519
- The SDK intentionally exposes only the ChatGPT-authenticated v3 transport. It
520
- does not retain the separately billed API-key Voice v2 WebSocket helpers.
532
+ The OAuth backend's event dialect is still experimental and is exposed
533
+ forward-compatibly through `LiveEvent` rather than rewritten into invented
534
+ public fields. The public primary `client.live.connect()` WebSocket is not
535
+ available through ChatGPT OAuth; use WebRTC plus the attached sideband.
521
536
 
522
537
  ### Embeddings
523
538
 
@@ -36,7 +36,7 @@ from codex_backend_sdk import OpenAI
36
36
  client = OpenAI().authenticate()
37
37
 
38
38
  response = client.responses.create(
39
- model="gpt-5.4",
39
+ model="gpt-5.5",
40
40
  input="Explain quicksort in one paragraph.",
41
41
  )
42
42
 
@@ -60,7 +60,8 @@ client.files # upload files for Apps/MCP parameters
60
60
  client.images # Codex-backed image generation and editing
61
61
  client.audio # ChatGPT-backed transcription
62
62
  client.embeddings # OpenAI embeddings endpoint through OAuth
63
- client.realtime # WebRTC call creation and Realtime connection headers
63
+ client.live # OpenAI-shaped GPT-Live creation and sideband attachment
64
+ client.realtime # additive low-level Codex Realtime v3 transport
64
65
  ```
65
66
 
66
67
  These resources follow `openai-python` conventions where the backend overlaps
@@ -113,7 +114,7 @@ dictionaries or raw streams when imposing a stable model would be misleading.
113
114
 
114
115
  ```python
115
116
  response = client.responses.create(
116
- model="gpt-5.4",
117
+ model="gpt-5.5",
117
118
  instructions="Be concise.",
118
119
  input="Summarize the CAP theorem.",
119
120
  reasoning={"effort": "medium", "summary": "auto"},
@@ -144,7 +145,7 @@ connection reusable across sequential turns:
144
145
 
145
146
  ```python
146
147
  with client.responses.websocket.connect() as ws:
147
- for event in ws.create({"model": "gpt-5.4", "input": "Say hello."}):
148
+ for event in ws.create({"model": "gpt-5.5", "input": "Say hello."}):
148
149
  if event.get("type") == "response.output_text.delta":
149
150
  print(event.get("delta", ""), end="")
150
151
  ```
@@ -168,7 +169,7 @@ print(client.responses.create(input=history).output_text)
168
169
 
169
170
  ```python
170
171
  compacted = client.responses.compact(
171
- model="gpt-5.4",
172
+ model="gpt-5.5",
172
173
  instructions="Preserve task-critical decisions and unresolved work.",
173
174
  input=history,
174
175
  )
@@ -239,7 +240,7 @@ print(result.output_parsed)
239
240
  for model in client.models.list():
240
241
  print(model.id, model.context_window, model.supported_reasoning_levels)
241
242
 
242
- model = client.models.retrieve("gpt-5.4")
243
+ model = client.models.retrieve("gpt-5.5")
243
244
  ```
244
245
 
245
246
  ### Upload a file
@@ -311,6 +312,10 @@ sports, and time commands. See the API reference for command validation.
311
312
  quota = client.codex.usage()
312
313
  daily = client.codex.usage_details.daily_token_breakdown()
313
314
  credits = client.codex.usage_details.credit_events()
315
+ plugin_metrics = client.codex.usage_details.plugin_usage_metrics(
316
+ start_date="2026-09-01",
317
+ end_date="2026-09-18",
318
+ )
314
319
 
315
320
  print(quota.get("rate_limit", {}).get("primary_window"))
316
321
  ```
@@ -414,6 +419,7 @@ tool annotations and own user confirmation; the SDK never auto-invokes tools.
414
419
  plugins = client.chatgpt.plugins.list_all(scope="GLOBAL")
415
420
  installed = client.chatgpt.plugins.installed_all()
416
421
  suggested = client.chatgpt.plugins.suggested()
422
+ home = client.chatgpt.plugins.home()
417
423
  skill = client.chatgpt.plugins.skill("plugins~...", "skill-name")
418
424
 
419
425
  checkout = client.chatgpt.plugins.bundles.extract_plugin(
@@ -462,33 +468,42 @@ return a typed in-memory object, bytes, `BytesIO`, a data URI, or a file path.
462
468
  ### Realtime voice
463
469
 
464
470
  ```python
465
- answer = client.realtime.calls.create_v3(
466
- sdp=offer_sdp,
471
+ live = client.live.create(
467
472
  session={
468
473
  "model": "gpt-live-1-codex",
469
474
  "instructions": "Speak naturally and stay concise.",
475
+ "delegation": {"type": "client"},
470
476
  },
477
+ transport={"type": "webrtc", "sdp": offer_sdp},
471
478
  )
472
- print(answer.answer_sdp)
479
+ apply_remote_sdp(live.transport.sdp)
480
+
481
+ with client.live.sideband.connect(session_id=live.session.id) as sideband:
482
+ for event in sideband:
483
+ print(event.type)
473
484
  ```
474
485
 
475
486
  Live probes confirmed `gpt-live-1-codex` and
476
487
  `gpt-live-1-boulder-alpha`. They are Codex Realtime v3 snapshots, not aliases
477
- for the public `gpt-realtime` family. The call response exposes `call_id`; join
478
- its OAuth-authenticated control and delegation channel with:
488
+ for the public `gpt-live-1` model. `client.live` follows the current
489
+ `openai-python` creation, response, and sideband idioms while adapting them to
490
+ the ChatGPT OAuth call transport.
491
+
492
+ The earlier low-level surface remains available for backend-specific code:
479
493
 
480
494
  ```python
481
- sideband = client.realtime.sideband.connect(
482
- call_id=answer.call_id,
483
- session_id="voice-session",
495
+ answer = client.realtime.calls.create_v3(
496
+ sdp=offer_sdp,
497
+ session={"model": "gpt-live-1-codex"},
484
498
  )
485
- sideband.send({"type": "delegation.context.append", "content": []})
486
- event = sideband.recv()
487
- sideband.close()
499
+ with client.realtime.sideband.connect(call_id=answer.call_id) as sideband:
500
+ sideband.send({"type": "session.close"})
488
501
  ```
489
502
 
490
- The SDK intentionally exposes only the ChatGPT-authenticated v3 transport. It
491
- does not retain the separately billed API-key Voice v2 WebSocket helpers.
503
+ The OAuth backend's event dialect is still experimental and is exposed
504
+ forward-compatibly through `LiveEvent` rather than rewritten into invented
505
+ public fields. The public primary `client.live.connect()` WebSocket is not
506
+ available through ChatGPT OAuth; use WebRTC plus the attached sideband.
492
507
 
493
508
  ### Embeddings
494
509
 
@@ -17,7 +17,7 @@ Quickstart:
17
17
  print(response.output_text)
18
18
  """
19
19
 
20
- __version__ = "0.5.2"
20
+ __version__ = "0.5.3"
21
21
 
22
22
  from .oauth import (
23
23
  DeviceCode,
@@ -57,6 +57,10 @@ from .codex_client import (
57
57
  Image,
58
58
  ImageResponse,
59
59
  ImagesResponse,
60
+ LiveCreateResponse,
61
+ LiveEvent,
62
+ LiveSession,
63
+ LiveTransport,
60
64
  RateLimitResetCredit,
61
65
  RateLimitResetCredits,
62
66
  ConsumeRateLimitResetCreditResponse,
@@ -102,6 +106,10 @@ __all__ = [
102
106
  "Image",
103
107
  "ImageResponse",
104
108
  "ImagesResponse",
109
+ "LiveCreateResponse",
110
+ "LiveEvent",
111
+ "LiveSession",
112
+ "LiveTransport",
105
113
  "RateLimitResetCredit",
106
114
  "RateLimitResetCredits",
107
115
  "ConsumeRateLimitResetCreditResponse",
@@ -30,7 +30,7 @@ class CodexClient:
30
30
  self,
31
31
  *,
32
32
  store: Optional[TokenStore] = None,
33
- model: str = "gpt-5.4",
33
+ model: str = "gpt-5.5",
34
34
  instructions: Optional[str] = None,
35
35
  timeout: float = 120,
36
36
  max_retries: int = 2,
@@ -44,7 +44,7 @@ class CodexClient:
44
44
  from .resources.openai_oauth import Audio, Embeddings
45
45
  from .resources.files import Files
46
46
  from .resources.images import Images
47
- from .resources.realtime import Realtime
47
+ from .resources.realtime import Live, Realtime
48
48
  from .resources.responses import Responses
49
49
 
50
50
  self._store = store
@@ -66,6 +66,7 @@ class CodexClient:
66
66
  self.responses = Responses(self)
67
67
  self.models = Models(self)
68
68
  self.realtime = Realtime(self)
69
+ self.live = Live(self)
69
70
  self.embeddings = Embeddings(self)
70
71
  self.audio = Audio(self)
71
72
  self.images = Images(self)
@@ -435,6 +435,32 @@ class RealtimeCallResponse(BinaryResponseContent):
435
435
  )
436
436
 
437
437
 
438
+ class LiveSession(CodexBaseModel):
439
+ """Resolved Live session identity returned by the OAuth adapter."""
440
+
441
+ id: str
442
+
443
+
444
+ class LiveTransport(CodexBaseModel):
445
+ """WebRTC answer using the public OpenAI Live response shape."""
446
+
447
+ type: Literal["webrtc"] = "webrtc"
448
+ sdp: str
449
+
450
+
451
+ class LiveCreateResponse(CodexBaseModel):
452
+ """OpenAI-compatible view of a Codex OAuth Realtime call response."""
453
+
454
+ session: LiveSession
455
+ transport: LiveTransport
456
+
457
+
458
+ class LiveEvent(CodexBaseModel):
459
+ """Forward-compatible Live sideband event with attribute access."""
460
+
461
+ type: str
462
+
463
+
438
464
  def _is_uuid(value: str) -> bool:
439
465
  if len(value) != 36:
440
466
  return False
@@ -8,6 +8,26 @@ from typing import Any
8
8
  import requests
9
9
 
10
10
 
11
+ _MAX_ERROR_DETAIL_CHARS = 4_000
12
+
13
+
14
+ def raise_for_status_with_detail(response: requests.Response) -> None:
15
+ """Raise the usual HTTPError while retaining a bounded backend error body."""
16
+ try:
17
+ response.raise_for_status()
18
+ except requests.HTTPError as error:
19
+ detail = response.text.strip()
20
+ if not detail:
21
+ raise
22
+ if len(detail) > _MAX_ERROR_DETAIL_CHARS:
23
+ detail = detail[:_MAX_ERROR_DETAIL_CHARS] + "..."
24
+ raise requests.HTTPError(
25
+ f"{error}. Backend response: {detail}",
26
+ response=response,
27
+ request=error.request,
28
+ ) from error
29
+
30
+
11
31
  def request_with_retries(
12
32
  session: requests.Session,
13
33
  method: str,
@@ -26,7 +46,7 @@ def request_with_retries(
26
46
  if should_retry_response(response, attempt, max_retries=max_retries):
27
47
  sleep_before_retry(response, attempt, retry_base_delay=retry_base_delay)
28
48
  continue
29
- response.raise_for_status()
49
+ raise_for_status_with_detail(response)
30
50
  return response
31
51
  except (requests.Timeout, requests.ConnectionError) as exc:
32
52
  last_error = exc
@@ -18,6 +18,10 @@ from ._models import (
18
18
  ImageData,
19
19
  ImageResponse,
20
20
  ImagesResponse,
21
+ LiveCreateResponse,
22
+ LiveEvent,
23
+ LiveSession,
24
+ LiveTransport,
21
25
  Model,
22
26
  MemorySummarizeOutput,
23
27
  MemorySummarizeResponse,
@@ -55,6 +59,10 @@ __all__ = [
55
59
  "ImageData",
56
60
  "ImageResponse",
57
61
  "ImagesResponse",
62
+ "LiveCreateResponse",
63
+ "LiveEvent",
64
+ "LiveSession",
65
+ "LiveTransport",
58
66
  "CompactedResponse",
59
67
  "MemorySummarizeOutput",
60
68
  "MemorySummarizeResponse",