codex-agent-framework 0.1.73__tar.gz → 0.1.75__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 (158) hide show
  1. {codex_agent_framework-0.1.73/codex_agent_framework.egg-info → codex_agent_framework-0.1.75}/PKG-INFO +1 -1
  2. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/browser.py +1 -1
  3. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/config.py +3 -0
  4. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/image.py +14 -0
  5. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/app.py +4 -0
  6. codex_agent_framework-0.1.75/codex_agent/version.py +1 -0
  7. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75/codex_agent_framework.egg-info}/PKG-INFO +1 -1
  8. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/pyproject.toml +1 -1
  9. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_builtin_config.py +14 -0
  10. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_chat.py +39 -0
  11. codex_agent_framework-0.1.73/codex_agent/version.py +0 -1
  12. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/CHANGELOG.md +0 -0
  13. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/LICENSE +0 -0
  14. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/MANIFEST.in +0 -0
  15. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/README.md +0 -0
  16. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/__init__.py +0 -0
  17. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/__main__.py +0 -0
  18. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/agent.py +0 -0
  19. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/agent_runtime.py +0 -0
  20. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/ai.py +0 -0
  21. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_commands.py +0 -0
  22. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/__init__.py +0 -0
  23. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/bash/__init__.py +0 -0
  24. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/bash/requirements.txt +0 -0
  25. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
  26. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/browser/requirements.txt +0 -0
  27. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/content/__init__.py +0 -0
  28. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/content/requirements.txt +0 -0
  29. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/content/system.py +0 -0
  30. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/content/vision.py +0 -0
  31. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/context/__init__.py +0 -0
  32. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
  33. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/desktop/requirements.txt +0 -0
  34. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/environment/__init__.py +0 -0
  35. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/environment/requirements.txt +0 -0
  36. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/files/__init__.py +0 -0
  37. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/files/requirements.txt +0 -0
  38. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/files/tools.py +0 -0
  39. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/image_generation/__init__.py +0 -0
  40. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/image_generation/image_generation_system_prompt.txt +0 -0
  41. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/image_generation/requirements.txt +0 -0
  42. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
  43. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/interface/requirements.txt +0 -0
  44. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/memory/__init__.py +0 -0
  45. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/memory/requirements.txt +0 -0
  46. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
  47. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/planner/requirements.txt +0 -0
  48. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/python/__init__.py +0 -0
  49. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/python/requirements.txt +0 -0
  50. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/realtime/__init__.py +0 -0
  51. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/realtime/audio.py +0 -0
  52. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/realtime/bridge.py +0 -0
  53. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/realtime/manager.py +0 -0
  54. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/realtime/requirements.txt +0 -0
  55. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/realtime/session.py +0 -0
  56. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
  57. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/scheduler/requirements.txt +0 -0
  58. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/subagents/__init__.py +0 -0
  59. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +0 -0
  60. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/subagents/requirements.txt +0 -0
  61. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/tts/__init__.py +0 -0
  62. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/tts/requirements.txt +0 -0
  63. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/builtin_plugins/web_search/__init__.py +0 -0
  64. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/cli/__init__.py +0 -0
  65. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/cli/headless.py +0 -0
  66. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/cli/main.py +0 -0
  67. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/cli/output.py +0 -0
  68. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/cli/root.py +0 -0
  69. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/cli/runner.py +0 -0
  70. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/client.py +0 -0
  71. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/command.py +0 -0
  72. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/context.py +0 -0
  73. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/desktop.py +0 -0
  74. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/event.py +0 -0
  75. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/get_text/__init__.py +0 -0
  76. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/get_text/default_gitignore +0 -0
  77. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/get_text/get_text.py +0 -0
  78. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/get_text/simpler_get_text.py +0 -0
  79. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/hooks.py +0 -0
  80. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/latex.py +0 -0
  81. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/mainloop.py +0 -0
  82. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/message.py +0 -0
  83. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/plugin.py +0 -0
  84. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/prompts/compaction_prompt.txt +0 -0
  85. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/prompts/system_prompt.txt +0 -0
  86. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/provider.py +0 -0
  87. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/runtime.py +0 -0
  88. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/scheduler.py +0 -0
  89. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/scripts/install-system-dependencies.sh +0 -0
  90. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/server/__init__.py +0 -0
  91. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/server/app.py +0 -0
  92. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/server/core.py +0 -0
  93. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/service.py +0 -0
  94. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/sessions.py +0 -0
  95. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/status.py +0 -0
  96. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/stream.py +0 -0
  97. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/stream_utils.py +0 -0
  98. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/token_counter.py +0 -0
  99. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tool.py +0 -0
  100. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tray.py +0 -0
  101. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/__init__.py +0 -0
  102. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/chat.py +0 -0
  103. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/lifecycle.py +0 -0
  104. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/log.py +0 -0
  105. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/perf.py +0 -0
  106. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/state.py +0 -0
  107. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/status_bar.py +0 -0
  108. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/stream_debug.py +0 -0
  109. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/style.py +0 -0
  110. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/transcript.py +0 -0
  111. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/tui/widgets.py +0 -0
  112. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/utils.py +0 -0
  113. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent/worker.py +0 -0
  114. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent_framework.egg-info/SOURCES.txt +0 -0
  115. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
  116. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent_framework.egg-info/entry_points.txt +0 -0
  117. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent_framework.egg-info/requires.txt +0 -0
  118. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/codex_agent_framework.egg-info/top_level.txt +0 -0
  119. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/dependencies.txt +0 -0
  120. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/setup.cfg +0 -0
  121. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent.py +0 -0
  122. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_audio_hooks.py +0 -0
  123. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_commands.py +0 -0
  124. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_context.py +0 -0
  125. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_desktop.py +0 -0
  126. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_environment.py +0 -0
  127. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_image_generation.py +0 -0
  128. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_observe.py +0 -0
  129. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_plugins.py +0 -0
  130. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_providers_config.py +0 -0
  131. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_realtime.py +0 -0
  132. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_response.py +0 -0
  133. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_runtime.py +0 -0
  134. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_sessions.py +0 -0
  135. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_subagents.py +0 -0
  136. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_tools.py +0 -0
  137. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_agent_turns.py +0 -0
  138. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_ai.py +0 -0
  139. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_browser.py +0 -0
  140. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_cli.py +0 -0
  141. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_cli_headless.py +0 -0
  142. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_cli_root.py +0 -0
  143. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_client.py +0 -0
  144. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_events.py +0 -0
  145. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_get_text_browser.py +0 -0
  146. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_hooks.py +0 -0
  147. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_image_message.py +0 -0
  148. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_local_desktop.py +0 -0
  149. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_memory.py +0 -0
  150. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_messages.py +0 -0
  151. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_planner.py +0 -0
  152. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_scheduler.py +0 -0
  153. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_server.py +0 -0
  154. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_service.py +0 -0
  155. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_token_counter.py +0 -0
  156. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_tui.py +0 -0
  157. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_utils.py +0 -0
  158. {codex_agent_framework-0.1.73 → codex_agent_framework-0.1.75}/tests/test_worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-agent-framework
3
- Version: 0.1.73
3
+ Version: 0.1.75
4
4
  Summary: A lightweight event-driven Codex agent runtime.
5
5
  Author: Baptiste
6
6
  License-Expression: MIT
@@ -252,7 +252,7 @@ class BrowserSession:
252
252
  async def __aenter__(self) -> "BrowserSession":
253
253
  return await self.start()
254
254
 
255
- async def __aexit__(self, exc_type, exc, tb) -> None:
255
+ async def __aexit__(self, _exc_type, _exc, _tb) -> None:
256
256
  await self.stop()
257
257
 
258
258
  async def new_page(self) -> Any:
@@ -353,6 +353,9 @@ class ConfigManager:
353
353
  legacy_agent_aliases=None,
354
354
  legacy_agent_sections=None,
355
355
  ):
356
+ # Kept for compatibility with older plugin config declarations; the
357
+ # current plugin-scoped config loader no longer needs these aliases.
358
+ del legacy_agent_aliases, legacy_agent_sections
356
359
  config = self.load_config(namespace, config_class=config_class, file=file, defaults=defaults)
357
360
  self.agent.config = self.config
358
361
  return config
@@ -18,6 +18,7 @@ IMAGE_DIR = 'images'
18
18
 
19
19
 
20
20
  def ext_to_mime(ext):
21
+ """Return the MIME type matching a common image extension."""
21
22
  ext = ext.lower().lstrip('.')
22
23
  if ext in ('jpg', 'jpeg'):
23
24
  return 'image/jpeg'
@@ -36,6 +37,7 @@ def _data_url(data, mime_type):
36
37
 
37
38
 
38
39
  def data_url_from_file(path):
40
+ """Read a local image file and encode it as a data URL."""
39
41
  ext = os.path.splitext(path)[1]
40
42
  mime_type = ext_to_mime(ext) or 'image/jpeg'
41
43
  with open(path, 'rb') as f:
@@ -64,6 +66,7 @@ def image_request_headers(url):
64
66
 
65
67
 
66
68
  def image_mime_from_source(source, content_type=None):
69
+ """Infer an image MIME type from headers, paths, or bytes-like sources."""
67
70
  content_type = (content_type or '').split(';')[0].strip()
68
71
  if content_type.startswith('image/'):
69
72
  return content_type
@@ -74,6 +77,7 @@ def image_mime_from_source(source, content_type=None):
74
77
 
75
78
 
76
79
  def fetch_image_bytes(url, timeout=15):
80
+ """Download image bytes and validate or infer their MIME type."""
77
81
  response = requests.get(url, timeout=timeout, headers=image_request_headers(url))
78
82
  response.raise_for_status()
79
83
 
@@ -94,11 +98,13 @@ def fetch_image_bytes(url, timeout=15):
94
98
 
95
99
 
96
100
  def data_url_from_url(url):
101
+ """Fetch a remote image URL and encode it as a data URL."""
97
102
  data, mime_type = fetch_image_bytes(url)
98
103
  return _data_url(data, mime_type)
99
104
 
100
105
 
101
106
  def persist_image_url(url):
107
+ """Download a remote image and persist it in the runtime image cache."""
102
108
  data, mime_type = fetch_image_bytes(url)
103
109
  ext = os.path.splitext(url.split('?', 1)[0])[1] or None
104
110
  mime_ext = {
@@ -113,6 +119,7 @@ def persist_image_url(url):
113
119
 
114
120
 
115
121
  def get_data_url(source):
122
+ """Return a data URL for a supported local path or remote URL source."""
116
123
  if isinstance(source, str) and os.path.isfile(source):
117
124
  return data_url_from_file(source)
118
125
  if isinstance(source, str) and source.startswith(('http://', 'https://')):
@@ -121,6 +128,7 @@ def get_data_url(source):
121
128
 
122
129
 
123
130
  def persist_image_bytes(data, name=None):
131
+ """Persist raw image bytes under the runtime image cache directory."""
124
132
  _, ext = os.path.splitext(name) if isinstance(name, str) else ('', '')
125
133
  ext = ext or guess_extension_from_bytes(data) or '.png'
126
134
 
@@ -134,10 +142,12 @@ def persist_image_bytes(data, name=None):
134
142
 
135
143
 
136
144
  def persist_bytesio(source):
145
+ """Persist a BytesIO image source, preserving its filename extension."""
137
146
  return persist_image_bytes(source.getvalue(), name=getattr(source, 'name', None))
138
147
 
139
148
 
140
149
  def image_name_from_source(source):
150
+ """Return a human-friendly image name for paths, URLs, or byte streams."""
141
151
  if isinstance(source, BytesIO) and getattr(source, 'name', None):
142
152
  return os.path.basename(source.name)
143
153
  if isinstance(source, str) and os.path.isfile(source):
@@ -386,6 +396,7 @@ class ImageMessage(Message):
386
396
  return "\n".join(parts)
387
397
 
388
398
  def as_bytesio(self):
399
+ """Return the in-memory image payload as bytes, when available."""
389
400
  data_url = self.get_base64()
390
401
  if not data_url:
391
402
  return None
@@ -396,6 +407,7 @@ class ImageMessage(Message):
396
407
  return BytesIO(base64.b64decode(match.group(1)))
397
408
 
398
409
  def image_size(self):
410
+ """Return image dimensions, or None when the payload is unavailable."""
399
411
  img_bytes = self.as_bytesio()
400
412
  if not img_bytes:
401
413
  return None
@@ -406,6 +418,7 @@ class ImageMessage(Message):
406
418
  return None
407
419
 
408
420
  def api_token_fingerprint(self):
421
+ """Return a stable fingerprint for cached image token estimates."""
409
422
  import hashlib
410
423
  import json
411
424
 
@@ -421,6 +434,7 @@ class ImageMessage(Message):
421
434
  return hashlib.sha256(text.encode("utf-8")).hexdigest()
422
435
 
423
436
  def compute_api_token_count(self, model=None):
437
+ """Estimate text-structure and visual-token cost for the image message."""
424
438
  size = self.image_size()
425
439
  text = (
426
440
  "The following image has been made available in context for visual analysis:\n"
@@ -68,6 +68,8 @@ class AgentTextualApp(App):
68
68
  self.handle_terminal_resize()
69
69
 
70
70
  def handle_terminal_resize(self, *, log_resized=False):
71
+ if log_resized:
72
+ self.stream_debug.record("tui_resized")
71
73
  self.resize_input()
72
74
  self.refresh_status()
73
75
 
@@ -148,6 +150,8 @@ class AgentTextualApp(App):
148
150
  def render_transcript(self, *, keep_scroll=False):
149
151
  # The widget timeline is updated incrementally. This method remains as a
150
152
  # compatibility shim for older call sites during the migration.
153
+ if keep_scroll:
154
+ self.stream_debug.record("tui_render_transcript_keep_scroll_ignored")
151
155
  return None
152
156
 
153
157
  def begin_transcript_batch(self):
@@ -0,0 +1 @@
1
+ __version__ = "0.1.75"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-agent-framework
3
- Version: 0.1.73
3
+ Version: 0.1.75
4
4
  Summary: A lightweight event-driven Codex agent runtime.
5
5
  Author: Baptiste
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codex-agent-framework"
7
- version = "0.1.73"
7
+ version = "0.1.75"
8
8
  description = "A lightweight event-driven Codex agent runtime."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -41,6 +41,20 @@ def test_parse_config_value_preserves_unknown_strings_and_values():
41
41
  assert parse_config_value({"already": "parsed"}) == {"already": "parsed"}
42
42
 
43
43
 
44
+ def test_apply_config_defaults_accepts_legacy_alias_arguments():
45
+ agent = DummyAgent()
46
+ manager = ConfigManager(agent)
47
+
48
+ config = manager.apply_config_defaults(
49
+ "legacy_plugin",
50
+ legacy_agent_aliases={"old": "new"},
51
+ legacy_agent_sections=["old_section"],
52
+ )
53
+
54
+ assert config is not None
55
+ assert agent.config is manager.config
56
+
57
+
44
58
  def test_builtin_plugin_enabled_none_loads_everything():
45
59
  manager = manager_with_builtin_field("builtin_plugins", None)
46
60
 
@@ -1354,6 +1354,45 @@ def test_chat_terminal_resize_keeps_input_and_status_fresh():
1354
1354
  assert calls == [("resize_input",), ("status",)]
1355
1355
 
1356
1356
 
1357
+ def test_chat_terminal_resize_can_log_legacy_resize_flag():
1358
+ calls = []
1359
+
1360
+ class StreamDebug:
1361
+ def record(self, name):
1362
+ calls.append(("record", name))
1363
+
1364
+ class App:
1365
+ stream_debug = StreamDebug()
1366
+
1367
+ def resize_input(self):
1368
+ calls.append(("resize_input",))
1369
+
1370
+ def refresh_status(self):
1371
+ calls.append(("status",))
1372
+
1373
+ from codex_agent.tui.app import AgentTextualApp
1374
+
1375
+ AgentTextualApp.handle_terminal_resize(App(), log_resized=True)
1376
+
1377
+ assert calls == [("record", "tui_resized"), ("resize_input",), ("status",)]
1378
+
1379
+
1380
+ def test_render_transcript_keep_scroll_flag_is_explicitly_ignored():
1381
+ calls = []
1382
+
1383
+ class StreamDebug:
1384
+ def record(self, name):
1385
+ calls.append(("record", name))
1386
+
1387
+ class App:
1388
+ stream_debug = StreamDebug()
1389
+
1390
+ from codex_agent.tui.app import AgentTextualApp
1391
+
1392
+ assert AgentTextualApp.render_transcript(App(), keep_scroll=True) is None
1393
+ assert calls == [("record", "tui_render_transcript_keep_scroll_ignored")]
1394
+
1395
+
1357
1396
  @pytest.mark.asyncio
1358
1397
  async def test_agent_textual_app_replay_hides_incremental_history_until_final_refresh(monkeypatch):
1359
1398
  class Client:
@@ -1 +0,0 @@
1
- __version__ = "0.1.73"