codex-agent-framework 0.1.56__tar.gz → 0.1.58__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.
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/CHANGELOG.md +19 -0
- {codex_agent_framework-0.1.56/codex_agent_framework.egg-info → codex_agent_framework-0.1.58}/PKG-INFO +1 -1
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/server/core.py +7 -4
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/stream_utils.py +42 -75
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/utils.py +30 -57
- codex_agent_framework-0.1.58/codex_agent/version.py +1 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58/codex_agent_framework.egg-info}/PKG-INFO +1 -1
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/pyproject.toml +1 -1
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_server.py +21 -9
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_utils.py +87 -1
- codex_agent_framework-0.1.56/codex_agent/version.py +0 -1
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/LICENSE +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/MANIFEST.in +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/README.md +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/__main__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/agent.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/agent_runtime.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/ai.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/browser.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_commands.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/bash/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/bash/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/browser/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/content/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/content/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/content/system.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/content/vision.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/context/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/desktop/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/environment/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/environment/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/files/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/files/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/files/tools.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/image_generation/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/image_generation/image_generation_system_prompt.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/image_generation/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/interface/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/memory/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/memory/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/planner/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/python/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/python/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/realtime/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/realtime/audio.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/realtime/bridge.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/realtime/manager.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/realtime/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/realtime/session.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/scheduler/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/subagents/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/subagents/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/tts/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/tts/requirements.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_plugins/web_search/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/cli/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/cli/headless.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/cli/main.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/cli/output.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/cli/root.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/cli/runner.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/client.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/command.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/config.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/context.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/desktop.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/event.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/get_text/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/get_text/default_gitignore +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/get_text/get_text.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/get_text/simpler_get_text.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/hooks.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/image.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/latex.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/mainloop.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/message.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/plugin.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/prompts/system_prompt.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/provider.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/runtime.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/scheduler.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/scripts/install-system-dependencies.sh +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/server/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/server/app.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/service.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/sessions.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/status.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/stream.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tool.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tray.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/__init__.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/app.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/chat.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/lifecycle.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/log.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/perf.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/state.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/status_bar.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/stream_debug.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/style.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/transcript.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/widgets.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/worker.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent_framework.egg-info/SOURCES.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent_framework.egg-info/entry_points.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent_framework.egg-info/requires.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent_framework.egg-info/top_level.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/dependencies.txt +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/setup.cfg +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_audio_hooks.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_commands.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_context.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_desktop.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_environment.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_image_generation.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_observe.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_plugins.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_providers_config.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_realtime.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_response.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_runtime.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_sessions.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_subagents.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_tools.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_turns.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_ai.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_browser.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_builtin_config.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_chat.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_cli.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_cli_headless.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_cli_root.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_client.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_events.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_get_text_browser.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_hooks.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_image_message.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_local_desktop.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_memory.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_messages.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_planner.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_scheduler.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_service.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_tui.py +0 -0
- {codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_worker.py +0 -0
|
@@ -4,6 +4,25 @@ 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.58] - 2026-05-17
|
|
8
|
+
### Fixed
|
|
9
|
+
- Keep active SSE event subscribers attached even when the FastAPI request handler thread that opened the `StreamingResponse` has ended, preventing TUI streams from degrading into ping-only connections that miss real assistant/tool events.
|
|
10
|
+
- Stop an SSE stream promptly if its subscriber has been removed from the active subscriber registry, forcing clients to reconnect and replay instead of staying apparently healthy while receiving only `server_ping` events.
|
|
11
|
+
|
|
12
|
+
### Tests
|
|
13
|
+
- Add server regressions covering registered subscribers independent of request-thread liveness and removed subscribers stopping instead of pinging forever; validate with targeted server/client/chat tests and the full offline CI suite (581 passed).
|
|
14
|
+
|
|
15
|
+
## [0.1.57] - 2026-05-17
|
|
16
|
+
### Fixed
|
|
17
|
+
- Fix stream helper fan-out edge cases so `Tee`, `Splitter`, and `MappingStreamSplitter` readers keep their own queues and reusable mapping splitters do not redirect old readers to new streams.
|
|
18
|
+
- Make `utils.Logger` create its parent directory before truncating the log file so first use works on fresh paths.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- Simplify small utility helpers for line-preserving truncation, message packing, and fenced stream pattern construction while preserving their existing behavior.
|
|
22
|
+
|
|
23
|
+
### Tests
|
|
24
|
+
- Add focused regression coverage for the stream helpers, logger initialization, and utility formatting/truncation helpers; validate with the full offline CI suite (580 passed).
|
|
25
|
+
|
|
7
26
|
## [0.1.56] - 2026-05-17
|
|
8
27
|
### Changed
|
|
9
28
|
- Replace the TUI chat surface with a widget-based timeline inspired by Textual chat patterns so live assistant output updates an active message widget instead of mutating a monolithic transcript buffer.
|
|
@@ -273,9 +273,12 @@ class AgentServer:
|
|
|
273
273
|
return False
|
|
274
274
|
|
|
275
275
|
def prune_subscribers(self):
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
276
|
+
"""Return active subscribers without pruning by request-thread liveness.
|
|
277
|
+
|
|
278
|
+
FastAPI may continue consuming a ``StreamingResponse`` after the
|
|
279
|
+
request handler thread that opened it is gone, so thread liveness is not
|
|
280
|
+
a reliable signal that an SSE subscriber is stale.
|
|
281
|
+
"""
|
|
279
282
|
return len(self.subscribers)
|
|
280
283
|
|
|
281
284
|
def subscriber_count(self):
|
|
@@ -367,7 +370,7 @@ class AgentServer:
|
|
|
367
370
|
try:
|
|
368
371
|
payload = subscriber.get(timeout=0.25)
|
|
369
372
|
except queue.Empty:
|
|
370
|
-
if self.shutdown_requested.is_set():
|
|
373
|
+
if self.shutdown_requested.is_set() or subscriber not in self.subscribers:
|
|
371
374
|
break
|
|
372
375
|
payload = modict(type="server_ping")
|
|
373
376
|
yield payload
|
|
@@ -53,17 +53,16 @@ class Tee:
|
|
|
53
53
|
for k in self.queues:
|
|
54
54
|
self.queues[k].put(END)
|
|
55
55
|
|
|
56
|
-
def tee(self,stream, n=2):
|
|
57
|
-
self.queues={k:Queue() for k in range(n)}
|
|
58
|
-
self.thread=Thread(target=self.target, args=(stream,),
|
|
56
|
+
def tee(self, stream, n=2):
|
|
57
|
+
self.queues = {k: Queue() for k in range(n)}
|
|
58
|
+
self.thread = Thread(target=self.target, args=(stream,), daemon=True)
|
|
59
59
|
self.thread.start()
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return tuple(readers.values())
|
|
60
|
+
|
|
61
|
+
def reader(queue):
|
|
62
|
+
while (processed_chunk := queue.get()) is not END:
|
|
63
|
+
yield processed_chunk
|
|
64
|
+
|
|
65
|
+
return tuple(reader(queue) for queue in self.queues.values())
|
|
67
66
|
|
|
68
67
|
class Splitter:
|
|
69
68
|
|
|
@@ -86,17 +85,16 @@ class Splitter:
|
|
|
86
85
|
self.queue_false.put(END)
|
|
87
86
|
|
|
88
87
|
def split(self, stream):
|
|
89
|
-
self.queue_true=Queue()
|
|
90
|
-
self.queue_false=Queue()
|
|
91
|
-
self.thread=Thread(target=self.target, args=(stream,),daemon=True)
|
|
88
|
+
self.queue_true = Queue()
|
|
89
|
+
self.queue_false = Queue()
|
|
90
|
+
self.thread = Thread(target=self.target, args=(stream,), daemon=True)
|
|
92
91
|
self.thread.start()
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def reader_false():
|
|
97
|
-
while (chunk:=self.queue_false.get()) is not END:
|
|
92
|
+
|
|
93
|
+
def reader(queue):
|
|
94
|
+
while (chunk := queue.get()) is not END:
|
|
98
95
|
yield chunk
|
|
99
|
-
|
|
96
|
+
|
|
97
|
+
return reader(self.queue_true), reader(self.queue_false)
|
|
100
98
|
|
|
101
99
|
class Streamer:
|
|
102
100
|
|
|
@@ -159,61 +157,27 @@ class StreamLogger(Streamer):
|
|
|
159
157
|
with open(self.file,'a', encoding='utf-8') as f:
|
|
160
158
|
f.write(output)
|
|
161
159
|
|
|
162
|
-
def fenced(start: Union[str,regex.Pattern,re.Pattern], end: Union[str,regex.Pattern,re.Pattern], flags=0) -> regex.Pattern:
|
|
163
|
-
r"""
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
The end delimiter can include backreferences to captured groups from the opening fence into placeholders in the closing fence.
|
|
168
|
-
|
|
169
|
-
The closing fence pattern may include placeholders in the form of "#1#" for the first captured group,
|
|
170
|
-
"#2#" for the second, or "#name#" for a named capturing group; these will be replaced by the appropriate
|
|
171
|
-
backreference. This mechanism is completely generic and does not enforce any specific delimiter shapes.
|
|
172
|
-
|
|
173
|
-
Example:
|
|
174
|
-
# Using a numeric placeholder:
|
|
175
|
-
pattern = fenced(r"START (\w+)", r"END #1#", flags=regex.DOTALL)
|
|
176
|
-
text = "START content END content"
|
|
177
|
-
match = pattern.match(text)
|
|
178
|
-
if match:
|
|
179
|
-
print(match.group())
|
|
180
|
-
|
|
181
|
-
# Using a named capturing group:
|
|
182
|
-
pattern = fenced(r"BEGIN (?P<tag>\w+)", r"FIN #tag#", flags=regex.DOTALL)
|
|
183
|
-
text = "BEGIN example FIN example"
|
|
184
|
-
match = pattern.match(text)
|
|
185
|
-
if match:
|
|
186
|
-
print(match.group())
|
|
187
|
-
|
|
188
|
-
:param start: Opening delimiter (str or regex.Pattern). May contain capturing groups.
|
|
189
|
-
:param end: Closing delimiter (str or regex.Pattern) which may include placeholders (e.g., "#1#", "#name#").
|
|
190
|
-
:param flags: Regex flags to modify behavior (e.g., regex.DOTALL, regex.MULTILINE).
|
|
191
|
-
:return: A compiled regex pattern.
|
|
160
|
+
def fenced(start: Union[str, regex.Pattern, re.Pattern], end: Union[str, regex.Pattern, re.Pattern], flags=0) -> regex.Pattern:
|
|
161
|
+
r"""Compile a fenced-content pattern with the inner text captured as ``content``.
|
|
162
|
+
|
|
163
|
+
``end`` may reference capture groups from ``start`` with ``#1#`` or
|
|
164
|
+
``#name#`` placeholders, which are converted to regex backreferences.
|
|
192
165
|
"""
|
|
193
|
-
def
|
|
194
|
-
if isinstance(pattern, (regex.Pattern,re.Pattern)):
|
|
195
|
-
return pattern.pattern
|
|
166
|
+
def pattern_source(pattern):
|
|
196
167
|
if isinstance(pattern, str):
|
|
197
168
|
return pattern
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
# Replace placeholders in end pattern with regex backrefs
|
|
204
|
-
def replace_placeholder(match):
|
|
169
|
+
if isinstance(pattern, (regex.Pattern, re.Pattern)):
|
|
170
|
+
return pattern.pattern
|
|
171
|
+
raise ValueError("`start` and `end` must be strings or regex Pattern objects")
|
|
172
|
+
|
|
173
|
+
def placeholder_to_backref(match):
|
|
205
174
|
key = match.group(1)
|
|
206
|
-
if key.isdigit()
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
# Named content group
|
|
213
|
-
inner = rf'(?P<content>(?:(?!{end_regex})[\s\S])*)'
|
|
214
|
-
|
|
215
|
-
full_pattern = rf'{start_regex}{inner}(?:{end_regex}|$)'
|
|
216
|
-
return regex.compile(full_pattern, flags)
|
|
175
|
+
return rf"\{key}" if key.isdigit() else rf"(?P={key})"
|
|
176
|
+
|
|
177
|
+
start_regex = pattern_source(start)
|
|
178
|
+
end_regex = regex.sub(r"#(\w+)#", placeholder_to_backref, pattern_source(end))
|
|
179
|
+
inner = rf"(?P<content>(?:(?!{end_regex})[\s\S])*)"
|
|
180
|
+
return regex.compile(rf"{start_regex}{inner}(?:{end_regex}|$)", flags)
|
|
217
181
|
|
|
218
182
|
def is_compiled_pattern(pattern):
|
|
219
183
|
if isinstance(pattern, (re.Pattern,regex.Pattern)):
|
|
@@ -528,16 +492,19 @@ class MappingStreamSplitter:
|
|
|
528
492
|
def maybe_init_readers(self, data):
|
|
529
493
|
for key in data.keys():
|
|
530
494
|
if key not in self.readers:
|
|
531
|
-
self.queues[key]=Queue()
|
|
532
|
-
|
|
533
|
-
|
|
495
|
+
queue = self.queues[key] = Queue()
|
|
496
|
+
|
|
497
|
+
def reader(queue=queue):
|
|
498
|
+
while (value := queue.get()) is not END:
|
|
534
499
|
if isinstance(value, StreamError):
|
|
535
500
|
raise value.error
|
|
536
501
|
yield value
|
|
537
|
-
|
|
502
|
+
|
|
503
|
+
self.readers[key] = reader()
|
|
538
504
|
|
|
539
505
|
def process(self,stream):
|
|
540
|
-
self.
|
|
506
|
+
self.readers = {}
|
|
507
|
+
self.queues = {}
|
|
541
508
|
self.done=False
|
|
542
509
|
if self.defaults:
|
|
543
510
|
self.maybe_init_readers(self.defaults)
|
|
@@ -230,69 +230,39 @@ def type_hierarchy(cls, root):
|
|
|
230
230
|
|
|
231
231
|
|
|
232
232
|
def truncate(string, max_tokens=2000, start_line=1, model=None):
|
|
233
|
-
"""
|
|
234
|
-
Truncate a string to a maximum number of tokens using line-based chunking.
|
|
235
|
-
|
|
236
|
-
Args:
|
|
237
|
-
string: The string to truncate
|
|
238
|
-
max_tokens: Maximum number of tokens to keep
|
|
239
|
-
start_line: The line number of the first line in the string (1-indexed).
|
|
240
|
-
Used for skipping content and tracking line numbers in truncation messages.
|
|
241
|
-
|
|
242
|
-
Returns:
|
|
243
|
-
Truncated string with indication of removed content
|
|
244
|
-
"""
|
|
245
|
-
# line-based pagination
|
|
233
|
+
"""Return a line-preserving prefix that fits within ``max_tokens``."""
|
|
246
234
|
lines = string.splitlines(keepends=True)
|
|
247
|
-
if start_line >
|
|
248
|
-
if start_line >
|
|
249
|
-
return ""
|
|
250
|
-
string = ''.join(lines[start_line - 1:])
|
|
251
|
-
lines = string.splitlines(keepends=True)
|
|
252
|
-
|
|
253
|
-
# Quick check - if already under limit after pagination, return as-is
|
|
254
|
-
tokens = tokenize(string, model=model)
|
|
255
|
-
if len(tokens) <= max_tokens:
|
|
256
|
-
return string
|
|
235
|
+
if start_line > len(lines):
|
|
236
|
+
return "" if start_line > 1 else string
|
|
257
237
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
result_lines = []
|
|
263
|
-
current_tokens = 0
|
|
238
|
+
lines = lines[max(0, start_line - 1):]
|
|
239
|
+
string = "".join(lines)
|
|
240
|
+
if len(tokenize(string, model=model)) <= max_tokens:
|
|
241
|
+
return string
|
|
264
242
|
|
|
243
|
+
kept_lines = []
|
|
244
|
+
kept_tokens = 0
|
|
265
245
|
for line in lines:
|
|
266
246
|
line_tokens = token_count(line, model=model)
|
|
267
|
-
if
|
|
268
|
-
result_lines.append(line)
|
|
269
|
-
current_tokens += line_tokens
|
|
270
|
-
else:
|
|
247
|
+
if kept_tokens + line_tokens > max_tokens:
|
|
271
248
|
break
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return result
|
|
287
|
-
else:
|
|
288
|
-
return f"[Lines {start_line}-{start_line + remaining_lines - 1} truncated - first line exceeds token limit]\n"
|
|
249
|
+
kept_lines.append(line)
|
|
250
|
+
kept_tokens += line_tokens
|
|
251
|
+
|
|
252
|
+
last_line = start_line + len(lines) - 1
|
|
253
|
+
if not kept_lines:
|
|
254
|
+
return f"[Lines {start_line}-{last_line} truncated - first line exceeds token limit]\n"
|
|
255
|
+
|
|
256
|
+
result = "".join(kept_lines)
|
|
257
|
+
first_truncated = start_line + len(kept_lines)
|
|
258
|
+
if first_truncated <= last_line:
|
|
259
|
+
if not result.endswith("\n"):
|
|
260
|
+
result += "\n"
|
|
261
|
+
result += f"\n...\n\n[Lines {first_truncated}-{last_line} truncated]\n"
|
|
262
|
+
return result
|
|
289
263
|
|
|
290
264
|
def pack_msgs(messages):
|
|
291
|
-
|
|
292
|
-
for message in messages:
|
|
293
|
-
text += message.name + ':\n'
|
|
294
|
-
text += message.content.strip() + '\n\n'
|
|
295
|
-
return text
|
|
265
|
+
return "".join(f"{message.name}:\n{message.content.strip()}\n\n" for message in messages)
|
|
296
266
|
|
|
297
267
|
def msg_token_count(msg, model=None):
|
|
298
268
|
return msg.api_token_count(model=model)
|
|
@@ -468,8 +438,11 @@ def upload_file_to_folder(source, folder, name=None):
|
|
|
468
438
|
class Logger:
|
|
469
439
|
|
|
470
440
|
def __init__(self,file=None):
|
|
471
|
-
self.file=file or root_join('logs',"log.txt")
|
|
472
|
-
|
|
441
|
+
self.file = os.fspath(file or root_join('logs', "log.txt"))
|
|
442
|
+
folder = os.path.dirname(self.file)
|
|
443
|
+
if folder:
|
|
444
|
+
os.makedirs(folder, exist_ok=True)
|
|
445
|
+
open(self.file, 'w', encoding='utf-8').close()
|
|
473
446
|
|
|
474
447
|
def log(self,message):
|
|
475
448
|
with open(self.file,'a',encoding="utf-8") as f:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.58"
|
|
@@ -513,22 +513,34 @@ def test_create_app_refuses_second_sse_client(monkeypatch):
|
|
|
513
513
|
service.subscribers.clear()
|
|
514
514
|
|
|
515
515
|
|
|
516
|
-
def
|
|
516
|
+
def test_agent_server_keeps_registered_event_subscribers_independent_of_request_thread():
|
|
517
517
|
agent = Agent(session="new")
|
|
518
518
|
service = AgentServer(InProcessAgentRuntime(agent))
|
|
519
|
+
stream = service.subscribe()
|
|
520
|
+
|
|
521
|
+
assert next(stream).type == "server_subscribed"
|
|
522
|
+
service.prune_subscribers()
|
|
523
|
+
service.publish(modict(type="response_content_delta_event", delta="still attached"))
|
|
519
524
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
525
|
+
assert next(stream).delta == "still attached"
|
|
526
|
+
stream.close()
|
|
527
|
+
assert len(service.subscribers) == 0
|
|
523
528
|
|
|
524
|
-
service.subscribers[queue.Queue()] = modict(thread=DeadThread())
|
|
525
529
|
|
|
530
|
+
def test_agent_server_stops_stream_removed_from_subscribers():
|
|
531
|
+
agent = Agent(session="new")
|
|
532
|
+
service = AgentServer(InProcessAgentRuntime(agent))
|
|
526
533
|
stream = service.subscribe()
|
|
534
|
+
|
|
535
|
+
assert next(stream).type == "server_subscribed"
|
|
536
|
+
service.subscribers.clear()
|
|
537
|
+
|
|
527
538
|
try:
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
539
|
+
next(stream)
|
|
540
|
+
except StopIteration:
|
|
541
|
+
pass
|
|
542
|
+
else:
|
|
543
|
+
raise AssertionError("Expected removed subscriber stream to stop instead of pinging forever")
|
|
532
544
|
|
|
533
545
|
|
|
534
546
|
def test_agent_server_stop_closes_event_streams(monkeypatch):
|
|
@@ -6,7 +6,7 @@ from PIL import Image as PILImage
|
|
|
6
6
|
from codex_agent.message import AssistantMessage, CompactionMessage, DeveloperMessage, InterruptMessage, ServerToolResponseMessage, ToolResultMessage, UserMessage
|
|
7
7
|
from codex_agent import utils
|
|
8
8
|
from codex_agent.image import ImageMessage, image_input_token_count
|
|
9
|
-
from codex_agent.stream_utils import MappingStreamProcessor
|
|
9
|
+
from codex_agent.stream_utils import MappingStreamProcessor, MappingStreamSplitter, Splitter, Tee, fenced
|
|
10
10
|
from codex_agent.utils import split_history_turns
|
|
11
11
|
from codex_agent.utils import project_python_env
|
|
12
12
|
|
|
@@ -29,6 +29,28 @@ def test_split_history_turns_groups_complete_agent_loop():
|
|
|
29
29
|
assert remainder == []
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def test_pack_msgs_formats_named_messages():
|
|
33
|
+
class Message:
|
|
34
|
+
def __init__(self, name, content):
|
|
35
|
+
self.name = name
|
|
36
|
+
self.content = content
|
|
37
|
+
|
|
38
|
+
messages = [
|
|
39
|
+
Message("user", " hello "),
|
|
40
|
+
Message("assistant", "done"),
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
assert utils.pack_msgs(messages) == "user:\nhello\n\nassistant:\ndone\n\n"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_logger_creates_parent_directory_and_truncates_file(tmp_path):
|
|
47
|
+
log_file = tmp_path / "logs" / "log.txt"
|
|
48
|
+
|
|
49
|
+
utils.Logger(file=log_file)
|
|
50
|
+
|
|
51
|
+
assert log_file.read_text(encoding="utf-8") == ""
|
|
52
|
+
|
|
53
|
+
|
|
32
54
|
def test_project_python_env_prefers_running_interpreter():
|
|
33
55
|
env = project_python_env(env={"PATH": "/usr/bin:/bin"}, executable="/opt/project-python/bin/python")
|
|
34
56
|
|
|
@@ -37,6 +59,30 @@ def test_project_python_env_prefers_running_interpreter():
|
|
|
37
59
|
assert env["PYTHON_EXECUTABLE"] == "/opt/project-python/bin/python"
|
|
38
60
|
|
|
39
61
|
|
|
62
|
+
def test_tee_fans_out_stream_to_independent_readers():
|
|
63
|
+
first, second = Tee().tee(iter(["a", "b"]), n=2)
|
|
64
|
+
|
|
65
|
+
assert list(first) == ["a", "b"]
|
|
66
|
+
assert list(second) == ["a", "b"]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_splitter_routes_stream_to_independent_readers():
|
|
70
|
+
even, odd = Splitter(lambda number: number % 2 == 0).split(iter([1, 2, 3, 4]))
|
|
71
|
+
|
|
72
|
+
assert list(even) == [2, 4]
|
|
73
|
+
assert list(odd) == [1, 3]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_mapping_stream_splitter_can_be_reused():
|
|
77
|
+
splitter = MappingStreamSplitter(threaded=False)
|
|
78
|
+
|
|
79
|
+
first = splitter.split(iter([{"text": "a"}]))
|
|
80
|
+
second = splitter.split(iter([{"text": "b"}]))
|
|
81
|
+
|
|
82
|
+
assert list(first["text"]) == ["a"]
|
|
83
|
+
assert list(second["text"]) == ["b"]
|
|
84
|
+
|
|
85
|
+
|
|
40
86
|
def test_mapping_stream_processor_is_direct_passthrough_without_processors():
|
|
41
87
|
source = iter([{"content": "a"}, {"content": "b"}])
|
|
42
88
|
processor = MappingStreamProcessor(processors={"content": []}, threaded=True)
|
|
@@ -47,6 +93,24 @@ def test_mapping_stream_processor_is_direct_passthrough_without_processors():
|
|
|
47
93
|
assert list(result) == [{"content": "a"}, {"content": "b"}]
|
|
48
94
|
|
|
49
95
|
|
|
96
|
+
def test_fenced_reuses_numbered_capture_in_closing_pattern():
|
|
97
|
+
pattern = fenced(r"BEGIN (\w+)\n", r"\nEND #1#")
|
|
98
|
+
|
|
99
|
+
match = pattern.fullmatch("BEGIN tag\nhello\nEND tag")
|
|
100
|
+
|
|
101
|
+
assert match is not None
|
|
102
|
+
assert match.group("content") == "hello"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_fenced_reuses_named_capture_in_closing_pattern():
|
|
106
|
+
pattern = fenced(r"<(?P<tag>\w+)>", r"</#tag#>")
|
|
107
|
+
|
|
108
|
+
match = pattern.fullmatch("<note>hello</note>")
|
|
109
|
+
|
|
110
|
+
assert match is not None
|
|
111
|
+
assert match.group("content") == "hello"
|
|
112
|
+
|
|
113
|
+
|
|
50
114
|
def test_read_document_content_adds_line_numbers_by_default(tmp_path):
|
|
51
115
|
file = tmp_path / "sample.txt"
|
|
52
116
|
file.write_text("alpha\nbeta\ngamma", encoding="utf-8")
|
|
@@ -390,6 +454,28 @@ def test_image_message_token_count_ignores_base64_text_volume():
|
|
|
390
454
|
assert message.estimated_token_count["gpt-5"]["count"] == count
|
|
391
455
|
|
|
392
456
|
|
|
457
|
+
def test_truncate_returns_requested_page_when_under_token_limit(monkeypatch):
|
|
458
|
+
monkeypatch.setattr(utils, "tokenize", lambda text, model=None: list(text))
|
|
459
|
+
monkeypatch.setattr(utils, "token_count", lambda text, model=None: len(text))
|
|
460
|
+
|
|
461
|
+
assert utils.truncate("a\nb\nc\n", max_tokens=10, start_line=2) == "b\nc\n"
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def test_truncate_appends_line_range_notice(monkeypatch):
|
|
465
|
+
monkeypatch.setattr(utils, "tokenize", lambda text, model=None: list(text))
|
|
466
|
+
monkeypatch.setattr(utils, "token_count", lambda text, model=None: len(text))
|
|
467
|
+
|
|
468
|
+
assert utils.truncate("aa\nbb\ncc\n", max_tokens=3) == "aa\n\n...\n\n[Lines 2-3 truncated]\n"
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def test_truncate_reports_first_line_when_it_exceeds_limit(monkeypatch):
|
|
472
|
+
monkeypatch.setattr(utils, "tokenize", lambda text, model=None: list(text))
|
|
473
|
+
monkeypatch.setattr(utils, "token_count", lambda text, model=None: len(text))
|
|
474
|
+
|
|
475
|
+
assert utils.truncate("aaaa\nbb\n", max_tokens=2, start_line=3) == ""
|
|
476
|
+
assert utils.truncate("aaaa\nbb\n", max_tokens=2) == "[Lines 1-2 truncated - first line exceeds token limit]\n"
|
|
477
|
+
|
|
478
|
+
|
|
393
479
|
def test_load_runtime_env_reads_runtime_dotenv(isolated_runtime_dir, monkeypatch):
|
|
394
480
|
isolated_runtime_dir.mkdir(parents=True, exist_ok=True)
|
|
395
481
|
env_file = isolated_runtime_dir / ".env"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.56"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/builtin_commands.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/get_text/__init__.py
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/get_text/default_gitignore
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/get_text/get_text.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/prompts/system_prompt.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/server/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/codex_agent/tui/stream_debug.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_audio_hooks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_environment.py
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_image_generation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_agent_providers_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.56 → codex_agent_framework-0.1.58}/tests/test_get_text_browser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|