codex-agent-framework 0.1.24__tar.gz → 0.1.26__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 (137) hide show
  1. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/CHANGELOG.md +12 -0
  2. {codex_agent_framework-0.1.24/codex_agent_framework.egg-info → codex_agent_framework-0.1.26}/PKG-INFO +19 -15
  3. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/README.md +17 -13
  4. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/__init__.py +19 -3
  5. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/agent.py +66 -75
  6. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/ai.py +158 -95
  7. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_commands.py +23 -26
  8. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/bash/__init__.py +7 -0
  9. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/bash/requirements.txt +1 -0
  10. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/browser/requirements.txt +2 -0
  11. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/content/__init__.py +10 -0
  12. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/content/requirements.txt +11 -0
  13. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/context/__init__.py +190 -0
  14. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/desktop/requirements.txt +4 -0
  15. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/environment/__init__.py +152 -0
  16. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/environment/requirements.txt +1 -0
  17. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/files/__init__.py +40 -0
  18. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/files/requirements.txt +10 -0
  19. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/image_generation/__init__.py +81 -0
  20. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/image_generation/requirements.txt +3 -0
  21. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/interface/__init__.py +15 -0
  22. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/interface/requirements.txt +1 -0
  23. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/memory/__init__.py +13 -4
  24. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/memory/requirements.txt +2 -0
  25. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/planner/requirements.txt +1 -0
  26. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/python/__init__.py +9 -0
  27. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/python/requirements.txt +2 -0
  28. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/realtime/__init__.py +131 -0
  29. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/realtime/audio.py +382 -0
  30. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/realtime/bridge.py +340 -0
  31. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/realtime/manager.py +263 -0
  32. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/realtime/requirements.txt +6 -0
  33. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/realtime/session.py +275 -0
  34. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/scheduler/requirements.txt +1 -0
  35. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/subagents/__init__.py +6 -4
  36. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +2 -2
  37. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/subagents/requirements.txt +1 -0
  38. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/tts/__init__.py +324 -0
  39. codex_agent_framework-0.1.26/codex_agent/builtin_plugins/tts/requirements.txt +4 -0
  40. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/cli/main.py +0 -1
  41. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/command.py +22 -9
  42. codex_agent_framework-0.1.26/codex_agent/config.py +284 -0
  43. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/context.py +3 -3
  44. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/event.py +85 -2
  45. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/hooks.py +25 -3
  46. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/mainloop.py +75 -3
  47. codex_agent_framework-0.1.26/codex_agent/plugin.py +559 -0
  48. codex_agent_framework-0.1.26/codex_agent/prompts/system_prompt.txt +55 -0
  49. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/provider.py +27 -9
  50. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/server/core.py +34 -2
  51. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/sessions.py +80 -18
  52. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/status.py +6 -1
  53. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/tool.py +34 -29
  54. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/tui/chat.py +339 -99
  55. codex_agent_framework-0.1.26/codex_agent/version.py +1 -0
  56. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/worker.py +88 -40
  57. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26/codex_agent_framework.egg-info}/PKG-INFO +19 -15
  58. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent_framework.egg-info/SOURCES.txt +24 -2
  59. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent_framework.egg-info/requires.txt +1 -1
  60. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/pyproject.toml +4 -3
  61. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_agent.py +1049 -209
  62. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_ai.py +95 -15
  63. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_chat.py +300 -37
  64. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_cli_headless.py +2 -2
  65. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_hooks.py +7 -7
  66. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_memory.py +65 -16
  67. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_planner.py +9 -9
  68. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_scheduler.py +5 -5
  69. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_server.py +78 -58
  70. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_worker.py +74 -51
  71. codex_agent_framework-0.1.24/codex_agent/builtin_plugins/environment/__init__.py +0 -21
  72. codex_agent_framework-0.1.24/codex_agent/builtin_plugins/files/__init__.py +0 -28
  73. codex_agent_framework-0.1.24/codex_agent/config.py +0 -172
  74. codex_agent_framework-0.1.24/codex_agent/plugin.py +0 -248
  75. codex_agent_framework-0.1.24/codex_agent/prompts/system_prompt.txt +0 -83
  76. codex_agent_framework-0.1.24/codex_agent/version.py +0 -1
  77. codex_agent_framework-0.1.24/codex_agent/voice.py +0 -362
  78. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/LICENSE +0 -0
  79. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/MANIFEST.in +0 -0
  80. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/__main__.py +0 -0
  81. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/agent_runtime.py +0 -0
  82. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/browser.py +0 -0
  83. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/__init__.py +0 -0
  84. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
  85. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/content/system.py +0 -0
  86. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/content/vision.py +0 -0
  87. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
  88. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/files/tools.py +0 -0
  89. {codex_agent_framework-0.1.24/codex_agent/prompts → codex_agent_framework-0.1.26/codex_agent/builtin_plugins/image_generation}/image_generation_system_prompt.txt +0 -0
  90. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
  91. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
  92. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/cli/__init__.py +0 -0
  93. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/cli/headless.py +0 -0
  94. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/cli/output.py +0 -0
  95. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/cli/root.py +0 -0
  96. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/cli/runner.py +0 -0
  97. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/client.py +0 -0
  98. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/desktop.py +0 -0
  99. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/get_text/__init__.py +0 -0
  100. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/get_text/default_gitignore +0 -0
  101. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/get_text/get_text.py +0 -0
  102. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/get_text/simpler_get_text.py +0 -0
  103. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/image.py +0 -0
  104. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/latex.py +0 -0
  105. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/message.py +0 -0
  106. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/runtime.py +0 -0
  107. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/scheduler.py +0 -0
  108. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/scripts/install-system-dependencies.sh +0 -0
  109. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/server/__init__.py +0 -0
  110. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/server/app.py +0 -0
  111. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/service.py +0 -0
  112. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/stream.py +0 -0
  113. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/stream_utils.py +0 -0
  114. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/tray.py +0 -0
  115. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/tui/__init__.py +0 -0
  116. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/tui/lifecycle.py +0 -0
  117. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent/utils.py +0 -0
  118. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
  119. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent_framework.egg-info/entry_points.txt +0 -0
  120. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/codex_agent_framework.egg-info/top_level.txt +0 -0
  121. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/dependencies.txt +0 -0
  122. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/setup.cfg +0 -0
  123. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_agent_runtime.py +0 -0
  124. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_browser.py +0 -0
  125. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_builtin_config.py +0 -0
  126. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_cli.py +0 -0
  127. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_cli_root.py +0 -0
  128. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_client.py +0 -0
  129. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_events.py +0 -0
  130. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_get_text_browser.py +0 -0
  131. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_image_message.py +0 -0
  132. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_local_desktop.py +0 -0
  133. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_messages.py +0 -0
  134. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_service.py +0 -0
  135. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_tray.py +0 -0
  136. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_tui.py +0 -0
  137. {codex_agent_framework-0.1.24 → codex_agent_framework-0.1.26}/tests/test_utils.py +0 -0
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  This project loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and uses semantic versioning where practical.
6
6
 
7
+ ## [0.1.25] - 2026-05-12
8
+ ### Added
9
+ - Add bundled plugin `requirements.txt` metadata for built-in capabilities and move image generation, realtime voice, and TTS into plugin-scoped packages.
10
+ - Add a selectable Textual TUI conversation pane with mouse scrolling, Ctrl+C selection copy, lazy older-transcript loading, and bottom-aware auto-scroll during streaming.
11
+
12
+ ### Changed
13
+ - Continue migrating built-in capability instructions and dependencies toward the plugin-first architecture.
14
+ - Remove legacy voice and prompt files that are now owned by dedicated built-in plugins.
15
+
16
+ ### Tests
17
+ - Expand regression coverage across agent/plugin/runtime/chat behavior; the current suite validates at 546 passed.
18
+
7
19
  ## [0.1.24] - 2026-05-10
8
20
  ### Added
9
21
  - Add dedicated slash-command lifecycle events, `SlashCommandStartEvent` and `SlashCommandDoneEvent`, with command name, arguments, status, result, and error metadata.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-agent-framework
3
- Version: 0.1.24
3
+ Version: 0.1.26
4
4
  Summary: A lightweight event-driven Codex agent runtime.
5
5
  Author: Baptiste
6
6
  License-Expression: MIT
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: audioop-lts; python_version >= "3.13"
19
19
  Requires-Dist: beautifulsoup4
20
- Requires-Dist: codex-backend-sdk
20
+ Requires-Dist: codex-backend-sdk>=0.3.1
21
21
  Requires-Dist: fastapi
22
22
  Requires-Dist: filetype
23
23
  Requires-Dist: modict
@@ -176,17 +176,16 @@ agent = Agent(session="latest")
176
176
  agent.interact()
177
177
  ```
178
178
 
179
- Voice is disabled by default. Enable it explicitly for a voice session:
179
+ Voice features are disabled by default. The realtime voice plugin uses Codex/ChatGPT auth through `codex-backend-sdk`; the legacy synchronized TTS stream still uses the OpenAI SDK speech endpoint when explicitly enabled.
180
180
 
181
181
  ```python
182
182
  from codex_agent import Agent
183
183
 
184
184
  agent = Agent(
185
185
  session="latest",
186
- openai_api_key="sk-...",
187
- voice_enabled=True,
188
- voice="nova",
186
+ builtin_plugins=["realtime", "memory", "planner", "scheduler"],
189
187
  )
188
+ agent.load_builtin_plugin("realtime")
190
189
  agent.interact()
191
190
  ```
192
191
 
@@ -473,7 +472,7 @@ The default agent includes practical local tools grouped as plugins:
473
472
  | Desktop | `desktop_start_session`, `desktop_run_commands` | Screenshot-backed Linux desktop automation. |
474
473
  | Subagents | `subagents_run` | Ephemeral child agents from predefined profiles. |
475
474
 
476
- Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
475
+ Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `context`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
477
476
 
478
477
  The `subagents` plugin ships an `explorer` profile: a read-only codebase inspection agent.
479
478
 
@@ -482,7 +481,7 @@ Select built-ins explicitly when you want a smaller agent:
482
481
  ```python
483
482
  agent = Agent(
484
483
  session="latest",
485
- builtin_plugins=["files", "content", "bash", "python", "memory", "planner"],
484
+ builtin_plugins=["files", "content", "bash", "python", "environment", "context", "memory", "planner"],
486
485
  )
487
486
  ```
488
487
 
@@ -534,8 +533,8 @@ from codex_agent import Agent
534
533
  agent = Agent(
535
534
  session="latest",
536
535
  model="gpt-5.5",
537
- reasoning_effort="medium",
538
- verbosity="medium",
536
+ reasoning={"effort": "medium", "summary": "auto"},
537
+ text={"verbosity": "medium"},
539
538
  input_token_limit=128000,
540
539
  auto_compact=True,
541
540
  web_search_enabled=False,
@@ -550,9 +549,8 @@ Or update saved config from the CLI:
550
549
  ```bash
551
550
  codex-agent config get
552
551
  codex-agent config set input_token_limit 128000
553
- codex-agent config set voice_enabled=true
554
- codex-agent config set builtin_plugins='["memory", "planner", "scheduler"]'
555
- codex-agent config set --no-save verbosity low
552
+ codex-agent config set builtin_plugins='["environment", "context", "memory", "planner", "scheduler", "realtime"]'
553
+ codex-agent config set --no-save text='{"verbosity":"low"}'
556
554
  ```
557
555
 
558
556
  Saved local state lives in `~/.codex-agent` by default:
@@ -567,7 +565,7 @@ logs/ detached server/tray logs
567
565
  memory.json durable semantic memory entries
568
566
  planner.json persistent named todos
569
567
  wakeups.json scheduled autonomous wakeups
570
- agent_config.json persisted runtime configuration
568
+ agent.config.json persisted agent configuration
571
569
  ```
572
570
 
573
571
  Override it with:
@@ -610,7 +608,7 @@ python -m pytest
610
608
  The current tree validates at:
611
609
 
612
610
  ```text
613
- 507 passed
611
+ 546 passed
614
612
  ```
615
613
 
616
614
  Build distributions:
@@ -622,8 +620,14 @@ python -m build
622
620
  python -m twine check dist/*
623
621
  ```
624
622
 
623
+ ### Auth model for backend-backed features
624
+
625
+ Core LLM calls, memory embeddings, non-streaming STT transcription, and realtime voice use the Codex backend SDK with Codex/ChatGPT auth. Legacy synchronized TTS playback and OpenAI input-token counting still use the OpenAI SDK and may require `openai_api_key` or `OPENAI_API_KEY` when those paths are enabled.
626
+
625
627
  ## Recent releases
626
628
 
629
+ - `0.1.26`: align SDK-facing config with Responses API shapes, add the `context` management plugin with selective non-destructive wrapper pruning, keep wrappers out of memory retrieval and compaction payloads, move embeddings/STT/realtime onto Codex backend auth, streamline voice/TTS plugin config, and improve TUI streaming/windowing.
630
+ - `0.1.25`: move built-in capabilities further into plugin-scoped modules, add bundled plugin requirement metadata, and replace the TUI conversation pane with a selectable rich chat area that preserves mouse scrolling, copy selection, lazy transcript loading, and bottom-aware auto-scroll.
627
631
  - `0.1.24`: add slash-command lifecycle events and TUI progress/result rendering so commands such as `/compact` and `/help` show running, done, failed, result, and error feedback instead of going silent.
628
632
  - `0.1.23`: add SDK event streaming with `Agent.stream()`, root `Agent.add_plugin()`, a faster README flow, the `~/.codex-agent` runtime default, text-first voice defaults, safer prompt templating limited to system messages, smarter `codex-agent` local-server attachment, and clearer TUI tool-call progress lines.
629
633
  - `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit; add finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, isolated event handlers, and shared version metadata.
@@ -127,17 +127,16 @@ agent = Agent(session="latest")
127
127
  agent.interact()
128
128
  ```
129
129
 
130
- Voice is disabled by default. Enable it explicitly for a voice session:
130
+ Voice features are disabled by default. The realtime voice plugin uses Codex/ChatGPT auth through `codex-backend-sdk`; the legacy synchronized TTS stream still uses the OpenAI SDK speech endpoint when explicitly enabled.
131
131
 
132
132
  ```python
133
133
  from codex_agent import Agent
134
134
 
135
135
  agent = Agent(
136
136
  session="latest",
137
- openai_api_key="sk-...",
138
- voice_enabled=True,
139
- voice="nova",
137
+ builtin_plugins=["realtime", "memory", "planner", "scheduler"],
140
138
  )
139
+ agent.load_builtin_plugin("realtime")
141
140
  agent.interact()
142
141
  ```
143
142
 
@@ -424,7 +423,7 @@ The default agent includes practical local tools grouped as plugins:
424
423
  | Desktop | `desktop_start_session`, `desktop_run_commands` | Screenshot-backed Linux desktop automation. |
425
424
  | Subagents | `subagents_run` | Ephemeral child agents from predefined profiles. |
426
425
 
427
- Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
426
+ Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `context`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
428
427
 
429
428
  The `subagents` plugin ships an `explorer` profile: a read-only codebase inspection agent.
430
429
 
@@ -433,7 +432,7 @@ Select built-ins explicitly when you want a smaller agent:
433
432
  ```python
434
433
  agent = Agent(
435
434
  session="latest",
436
- builtin_plugins=["files", "content", "bash", "python", "memory", "planner"],
435
+ builtin_plugins=["files", "content", "bash", "python", "environment", "context", "memory", "planner"],
437
436
  )
438
437
  ```
439
438
 
@@ -485,8 +484,8 @@ from codex_agent import Agent
485
484
  agent = Agent(
486
485
  session="latest",
487
486
  model="gpt-5.5",
488
- reasoning_effort="medium",
489
- verbosity="medium",
487
+ reasoning={"effort": "medium", "summary": "auto"},
488
+ text={"verbosity": "medium"},
490
489
  input_token_limit=128000,
491
490
  auto_compact=True,
492
491
  web_search_enabled=False,
@@ -501,9 +500,8 @@ Or update saved config from the CLI:
501
500
  ```bash
502
501
  codex-agent config get
503
502
  codex-agent config set input_token_limit 128000
504
- codex-agent config set voice_enabled=true
505
- codex-agent config set builtin_plugins='["memory", "planner", "scheduler"]'
506
- codex-agent config set --no-save verbosity low
503
+ codex-agent config set builtin_plugins='["environment", "context", "memory", "planner", "scheduler", "realtime"]'
504
+ codex-agent config set --no-save text='{"verbosity":"low"}'
507
505
  ```
508
506
 
509
507
  Saved local state lives in `~/.codex-agent` by default:
@@ -518,7 +516,7 @@ logs/ detached server/tray logs
518
516
  memory.json durable semantic memory entries
519
517
  planner.json persistent named todos
520
518
  wakeups.json scheduled autonomous wakeups
521
- agent_config.json persisted runtime configuration
519
+ agent.config.json persisted agent configuration
522
520
  ```
523
521
 
524
522
  Override it with:
@@ -561,7 +559,7 @@ python -m pytest
561
559
  The current tree validates at:
562
560
 
563
561
  ```text
564
- 507 passed
562
+ 546 passed
565
563
  ```
566
564
 
567
565
  Build distributions:
@@ -573,8 +571,14 @@ python -m build
573
571
  python -m twine check dist/*
574
572
  ```
575
573
 
574
+ ### Auth model for backend-backed features
575
+
576
+ Core LLM calls, memory embeddings, non-streaming STT transcription, and realtime voice use the Codex backend SDK with Codex/ChatGPT auth. Legacy synchronized TTS playback and OpenAI input-token counting still use the OpenAI SDK and may require `openai_api_key` or `OPENAI_API_KEY` when those paths are enabled.
577
+
576
578
  ## Recent releases
577
579
 
580
+ - `0.1.26`: align SDK-facing config with Responses API shapes, add the `context` management plugin with selective non-destructive wrapper pruning, keep wrappers out of memory retrieval and compaction payloads, move embeddings/STT/realtime onto Codex backend auth, streamline voice/TTS plugin config, and improve TUI streaming/windowing.
581
+ - `0.1.25`: move built-in capabilities further into plugin-scoped modules, add bundled plugin requirement metadata, and replace the TUI conversation pane with a selectable rich chat area that preserves mouse scrolling, copy selection, lazy transcript loading, and bottom-aware auto-scroll.
578
582
  - `0.1.24`: add slash-command lifecycle events and TUI progress/result rendering so commands such as `/compact` and `/help` show running, done, failed, result, and error feedback instead of going silent.
579
583
  - `0.1.23`: add SDK event streaming with `Agent.stream()`, root `Agent.add_plugin()`, a faster README flow, the `~/.codex-agent` runtime default, text-first voice defaults, safer prompt templating limited to system messages, smarter `codex-agent` local-server attachment, and clearer TUI tool-call progress lines.
580
584
  - `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit; add finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, isolated event handlers, and shared version metadata.
@@ -13,6 +13,7 @@ from .event import (
13
13
  AssistantTurnStartEvent,
14
14
  AudioPlaybackEvent,
15
15
  CompactionCompletedEvent,
16
+ CompactionFailedEvent,
16
17
  CompactionRequestedEvent,
17
18
  Event,
18
19
  EventBus,
@@ -25,6 +26,13 @@ from .event import (
25
26
  ResponseReasoningDeltaEvent,
26
27
  ResponseStartEvent,
27
28
  ResponseToolCallsDeltaEvent,
29
+ RealtimeApiEvent,
30
+ RealtimeErrorEvent,
31
+ RealtimeSessionRefreshEvent,
32
+ RealtimeStartedEvent,
33
+ RealtimeStartingEvent,
34
+ RealtimeStoppedEvent,
35
+ RuntimeStateChangedEvent,
28
36
  ServerToolCallEvent,
29
37
  SessionDeletedEvent,
30
38
  SlashCommandDoneEvent,
@@ -50,14 +58,14 @@ from .message import (
50
58
  )
51
59
  from .image import ImageMessage
52
60
  from .mainloop import MainLoopManager
53
- from .plugin import Plugin, PluginsManager, event_handler, hook_handler
61
+ from .plugin import Plugin, PluginsManager, event_handler, hook_handler, stream_processor
54
62
  from .command import AgentCommand, AgentFuture, AgentTurn, CommandManager, command
55
63
  from .stream import AgentStream
56
64
  from .provider import ProvidersManager, provider
57
65
  from .runtime import RuntimeManager
58
66
  from .sessions import AgentSession, SessionsManager
59
67
  from .status import StatusManager
60
- from .tool import ImageGenerationTool, ServerTool, Tool, ToolsManager, WebSearchTool, get_agent, get_current_call_id, tool
68
+ from .tool import ServerTool, Tool, ToolsManager, WebSearchTool, get_agent, get_current_call_id, tool
61
69
  from .worker import SummarizerWorker, TurnSummaryWorker, Worker
62
70
  from .version import __version__
63
71
 
@@ -78,6 +86,7 @@ __all__ = [
78
86
  "AssistantTurnStartEvent",
79
87
  "AudioPlaybackEvent",
80
88
  "CompactionCompletedEvent",
89
+ "CompactionFailedEvent",
81
90
  "CompactionRequestedEvent",
82
91
  "Event",
83
92
  "EventBus",
@@ -90,6 +99,13 @@ __all__ = [
90
99
  "ResponseReasoningDeltaEvent",
91
100
  "ResponseStartEvent",
92
101
  "ResponseToolCallsDeltaEvent",
102
+ "RealtimeApiEvent",
103
+ "RealtimeErrorEvent",
104
+ "RealtimeSessionRefreshEvent",
105
+ "RealtimeStartedEvent",
106
+ "RealtimeStartingEvent",
107
+ "RealtimeStoppedEvent",
108
+ "RuntimeStateChangedEvent",
93
109
  "ServerToolCallEvent",
94
110
  "SessionDeletedEvent",
95
111
  "SlashCommandDoneEvent",
@@ -116,6 +132,7 @@ __all__ = [
116
132
  "PluginsManager",
117
133
  "event_handler",
118
134
  "hook_handler",
135
+ "stream_processor",
119
136
  "ProvidersManager",
120
137
  "AgentCommand",
121
138
  "AgentFuture",
@@ -128,7 +145,6 @@ __all__ = [
128
145
  "AgentSession",
129
146
  "SessionsManager",
130
147
  "StatusManager",
131
- "ImageGenerationTool",
132
148
  "ServerTool",
133
149
  "Tool",
134
150
  "ToolsManager",
@@ -1,6 +1,7 @@
1
1
  from .utils import text_content, ensure_runtime_dir, upload_file_to_folder, project_python_env, runtime_join, root_join
2
2
  import os
3
- from .message import DeveloperMessage, ServerToolResponseMessage, SystemMessage, ToolResultMessage, UserMessage, message_from_data
3
+ from modict import modict
4
+ from .message import DeveloperMessage, ServerToolResponseMessage, ToolResultMessage, UserMessage, message_from_data
4
5
  from .image import ImageMessage
5
6
  from .command import CommandManager
6
7
  from .config import ConfigManager
@@ -13,11 +14,9 @@ from .runtime import RuntimeManager
13
14
  from .scheduler import AgentScheduler
14
15
  from .sessions import SessionsManager
15
16
  from .status import StatusManager
16
- from .tool import ImageGenerationTool, ToolsManager, reset_current_agent, set_current_agent
17
+ from .tool import ToolsManager, reset_current_agent, set_current_agent
17
18
  from .ai import AIClient
18
- from .voice import VoiceProcessor
19
- from .latex import LaTeXProcessor
20
- from .event import AssistantInterruptRequestedEvent, AssistantInterrupted, AssistantInterruptedEvent, AudioPlaybackEvent, EventBus
19
+ from .event import AssistantInterruptRequestedEvent, AssistantInterrupted, AssistantInterruptedEvent, EventBus
21
20
  from threading import Event as ThreadEvent
22
21
 
23
22
  class Agent:
@@ -51,7 +50,8 @@ class Agent:
51
50
  self.runtime=RuntimeManager(self)
52
51
  self.scheduler=AgentScheduler(self)
53
52
  self.hooks=HookManager(self)
54
- self.on(AudioPlaybackEvent, self.handle_audio_playback)
53
+ self.stream_processors=modict()
54
+ self.stream_processor_owners={}
55
55
  self.mainloop_manager=MainLoopManager(self)
56
56
  self._interrupt_requested=ThreadEvent()
57
57
  self.current_session_id=None
@@ -63,9 +63,6 @@ class Agent:
63
63
  self.command_manager.init_folder()
64
64
  self.plugins_manager.init_folder()
65
65
  self.ai=AIClient(self)
66
- self.voice=VoiceProcessor(self)
67
- self.latex=LaTeXProcessor()
68
- self.content_processors=[self.voice]
69
66
  self.command_manager.init_builtin()
70
67
  self.plugins_manager.init_builtin()
71
68
  self.plugins_manager.init_runtime()
@@ -74,13 +71,13 @@ class Agent:
74
71
  self.tools_manager.apply_config_exclusions()
75
72
  self.start_new_session() if session == "new" else self.load_session(session)
76
73
 
77
- def on(self, event_type, handler=None):
74
+ def on(self, event_type, handler=None, owner=None):
78
75
  """Register an event handler.
79
76
 
80
77
  Can be used as ``agent.on(ResponseContentDeltaEvent, handler)`` or as
81
78
  ``@agent.on(ResponseContentDeltaEvent)``.
82
79
  """
83
- return self.events.on(event_type, handler)
80
+ return self.events.on(event_type, handler, owner=owner)
84
81
 
85
82
  def emit(self, event_type, **data):
86
83
  event = self.events.emit(event_type, **data)
@@ -203,8 +200,13 @@ class Agent:
203
200
  def save_session(self):
204
201
  return self.sessions_manager.save()
205
202
 
206
- def compact_session(self, client=None, model=None, instructions=None):
207
- return self.sessions_manager.compact(client=client, model=model, instructions=instructions)
203
+ def compact_session(self, client=None, model=None, instructions=None, max_compacted_turns=None):
204
+ return self.sessions_manager.compact(
205
+ client=client,
206
+ model=model,
207
+ instructions=instructions,
208
+ max_compacted_turns=max_compacted_turns,
209
+ )
208
210
 
209
211
  def add_message(self,msg,pending=False):
210
212
  """Queue a message for the next pending flush, except tool results."""
@@ -238,7 +240,7 @@ class Agent:
238
240
  self.add_message(img,pending=pending)
239
241
  return img
240
242
 
241
- def add_tool(self,func=None,name=None,description=None,parameters=None,required=None,tool_type=None,format=None):
243
+ def add_tool(self,func=None,name=None,description=None,parameters=None,required=None,tool_type=None,format=None,owner=None):
242
244
  return self.tools_manager.add(
243
245
  func=func,
244
246
  name=name,
@@ -247,18 +249,59 @@ class Agent:
247
249
  required=required,
248
250
  tool_type=tool_type,
249
251
  format=format,
252
+ owner=owner,
250
253
  )
251
254
 
252
- def add_provider(self, func=None, name=None):
253
- return self.providers_manager.add(func=func, name=name)
255
+ def add_provider(self, func=None, name=None, owner=None):
256
+ return self.providers_manager.add(func=func, name=name, owner=owner)
254
257
 
255
- def add_command(self, func=None, name=None):
256
- return self.command_manager.add(func, name=name)
258
+ def add_command(self, func=None, name=None, owner=None):
259
+ return self.command_manager.add(func, name=name, owner=owner)
257
260
 
258
261
  def add_plugin(self, plugin):
259
262
  return self.plugins_manager.add_plugin(plugin)
260
263
 
261
- def add_hook(self, key, func=None):
264
+ def load_builtin_plugin(self, name):
265
+ return self.plugins_manager.load_builtin_plugin(name)
266
+
267
+ def load_runtime_plugin(self, name_or_path):
268
+ return self.plugins_manager.load_runtime_plugin(name_or_path)
269
+
270
+ def unload_plugin(self, plugin_or_name, timeout=None):
271
+ return self.plugins_manager.unload_plugin(plugin_or_name, timeout=timeout)
272
+
273
+ def reload_plugin(self, plugin_or_name, timeout=None):
274
+ return self.plugins_manager.reload_plugin(plugin_or_name, timeout=timeout)
275
+
276
+ def add_stream_processor(self, key, processor, owner=None):
277
+ processors = self.stream_processors.setdefault(str(key), [])
278
+ processors.append(processor)
279
+ if owner is not None:
280
+ self.stream_processor_owners.setdefault(str(key), {})[processor] = owner
281
+ return processor
282
+
283
+ def get_stream_processors(self, key):
284
+ return list(self.stream_processors.get(str(key), []))
285
+
286
+ def remove_stream_processors_by_owner(self, owner):
287
+ removed = modict()
288
+ for key, processors in list(self.stream_processors.items()):
289
+ owners = self.stream_processor_owners.get(key, {})
290
+ kept = []
291
+ for processor in processors:
292
+ if owners.get(processor) == owner:
293
+ removed.setdefault(key, []).append(processor)
294
+ owners.pop(processor, None)
295
+ else:
296
+ kept.append(processor)
297
+ if kept:
298
+ self.stream_processors[key] = kept
299
+ else:
300
+ self.stream_processors.pop(key, None)
301
+ self.stream_processor_owners.pop(key, None)
302
+ return removed
303
+
304
+ def add_hook(self, key, func=None, owner=None):
262
305
  """Register a runtime hook.
263
306
 
264
307
  Hooks are callable extension points keyed by name. They are runtime
@@ -267,13 +310,13 @@ class Agent:
267
310
  """
268
311
  if func is None:
269
312
  def decorator(f):
270
- return self.add_hook(key, f)
313
+ return self.add_hook(key, f, owner=owner)
271
314
  return decorator
272
315
 
273
316
  if hasattr(self, "mainloop_manager") and self.mainloop_manager.should_queue_state_command():
274
- return self.submit("add_hook", key=key, func=func).wait().result
317
+ return self.submit("add_hook", key=key, func=func, owner=owner).wait().result
275
318
 
276
- return self.hooks.add(key, func)
319
+ return self.hooks.add(key, func, owner=owner)
277
320
 
278
321
  def has_hook(self, key):
279
322
  return self.hooks.has(key)
@@ -298,44 +341,6 @@ class Agent:
298
341
  def get_status(self):
299
342
  return self.status_manager.get_status()
300
343
 
301
- def create_image(
302
- self,
303
- prompt,
304
- input_images=None,
305
- model="gpt-5.4",
306
- reasoning_effort="medium",
307
- verbosity="medium",
308
- output_format="png",
309
- size=None,
310
- quality=None,
311
- background=None,
312
- moderation=None,
313
- ):
314
- """Generate an image directly and return the saved image path."""
315
- content = [{"type": "text", "text": prompt}]
316
- for source in input_images or []:
317
- content.extend(ImageMessage(content=source).content_to_response_parts())
318
-
319
- system_prompt = text_content(os.path.join(os.path.dirname(__file__), "prompts", "image_generation_system_prompt.txt"))
320
- message = self.ai.run(
321
- messages=[SystemMessage(content=system_prompt), UserMessage(content=content)],
322
- tools=[ImageGenerationTool(
323
- output_format=output_format,
324
- size=size,
325
- quality=quality,
326
- background=background,
327
- moderation=moderation,
328
- ).to_response_tool()],
329
- model=model,
330
- reasoning_effort=reasoning_effort,
331
- verbosity=verbosity,
332
- )
333
- for item in message.output_items:
334
- if item.get("type") == "image_generation_call":
335
- return ServerToolResponseMessage(item=item).content
336
- else:
337
- raise RuntimeError("The image_generation tool did not return an image.")
338
-
339
344
  def get_response(self):
340
345
  """Run the model, emit response events, and store the final message.
341
346
 
@@ -358,7 +363,7 @@ class Agent:
358
363
  messages=messages,
359
364
  tools=self.tools_manager.get_response_tools(),
360
365
  prompt_cache_key=self.current_session_id,
361
- **self.config.extract('model','reasoning_effort','verbosity','parallel_tool_calls')
366
+ **self.config.extract('model','reasoning','text','parallel_tool_calls')
362
367
  )
363
368
  self.sessions_manager.append_message(message)
364
369
  for item in message.output_items:
@@ -366,20 +371,6 @@ class Agent:
366
371
  self.sessions_manager.append_message(ServerToolResponseMessage(item=item))
367
372
  return message
368
373
 
369
- def speak(self,text,**kwargs):
370
- audio=self.ai.text_to_audio(text,**kwargs)
371
- if audio is not None:
372
- self.emit(AudioPlaybackEvent, audio=audio)
373
-
374
- def handle_audio_playback(self, event):
375
- audio = event.get("audio")
376
- if audio is None:
377
- return None
378
- if self.has_hook("audio_playback_hook"):
379
- return self.run_hooks("audio_playback_hook", audio)
380
- from .voice import silent_play
381
- return silent_play(audio)
382
-
383
374
  def listen(self, source, language=None, **kwargs):
384
375
  """
385
376
  description: |