codex-agent-framework 0.1.60__tar.gz → 0.1.61__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.60/codex_agent_framework.egg-info → codex_agent_framework-0.1.61}/PKG-INFO +1 -1
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/context/__init__.py +2 -1
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/config.py +3 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/context.py +5 -1
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/message.py +23 -13
- codex_agent_framework-0.1.61/codex_agent/prompts/compaction_prompt.txt +17 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/sessions.py +3 -1
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/status.py +9 -3
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/status_bar.py +35 -10
- codex_agent_framework-0.1.61/codex_agent/version.py +1 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61/codex_agent_framework.egg-info}/PKG-INFO +1 -1
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent_framework.egg-info/SOURCES.txt +1 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/pyproject.toml +1 -1
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_context.py +28 -3
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_plugins.py +1 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_response.py +1 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_chat.py +20 -4
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_messages.py +9 -7
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_token_counter.py +11 -7
- codex_agent_framework-0.1.60/codex_agent/version.py +0 -1
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/CHANGELOG.md +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/LICENSE +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/MANIFEST.in +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/README.md +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/__main__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/agent.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/agent_runtime.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/ai.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/browser.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_commands.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/bash/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/bash/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/browser/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/content/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/content/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/content/system.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/content/vision.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/desktop/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/environment/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/environment/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/files/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/files/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/files/tools.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/image_generation/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/image_generation/image_generation_system_prompt.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/image_generation/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/interface/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/memory/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/memory/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/planner/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/python/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/python/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/realtime/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/realtime/audio.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/realtime/bridge.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/realtime/manager.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/realtime/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/realtime/session.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/scheduler/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/subagents/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/subagents/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/tts/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/tts/requirements.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/builtin_plugins/web_search/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/cli/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/cli/headless.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/cli/main.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/cli/output.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/cli/root.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/cli/runner.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/client.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/command.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/desktop.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/event.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/get_text/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/get_text/default_gitignore +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/get_text/get_text.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/get_text/simpler_get_text.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/hooks.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/image.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/latex.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/mainloop.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/plugin.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/prompts/system_prompt.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/provider.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/runtime.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/scheduler.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/scripts/install-system-dependencies.sh +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/server/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/server/app.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/server/core.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/service.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/stream.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/stream_utils.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/token_counter.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tool.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tray.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/__init__.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/app.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/chat.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/lifecycle.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/log.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/perf.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/state.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/stream_debug.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/style.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/transcript.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/tui/widgets.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/utils.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/worker.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent_framework.egg-info/entry_points.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent_framework.egg-info/requires.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent_framework.egg-info/top_level.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/dependencies.txt +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/setup.cfg +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_audio_hooks.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_commands.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_desktop.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_environment.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_image_generation.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_observe.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_providers_config.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_realtime.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_runtime.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_sessions.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_subagents.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_tools.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_turns.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_ai.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_browser.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_builtin_config.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_cli.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_cli_headless.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_cli_root.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_client.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_events.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_get_text_browser.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_hooks.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_image_message.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_local_desktop.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_memory.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_planner.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_scheduler.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_server.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_service.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_tui.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_utils.py +0 -0
- {codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_worker.py +0 -0
|
@@ -37,6 +37,7 @@ Tool result wrappers expose stable `wrapper_id` values in their XML representati
|
|
|
37
37
|
vanished_wrapper_messages=status.get("vanished_wrapper_messages", 0),
|
|
38
38
|
total_wrapper_messages=status.get("total_wrapper_messages", 0),
|
|
39
39
|
base_context_tokens=status.get("base_context_tokens", status.used_tokens),
|
|
40
|
+
provider_context_tokens=status.get("provider_context_tokens", 0),
|
|
40
41
|
active_wrapper_tokens=status.get("active_wrapper_tokens", 0),
|
|
41
42
|
vanished_wrapper_tokens=status.get("vanished_wrapper_tokens", 0),
|
|
42
43
|
compactable_turns=status.get("compactable_turns", 0),
|
|
@@ -57,7 +58,7 @@ Tool result wrappers expose stable `wrapper_id` values in their XML representati
|
|
|
57
58
|
return "\n".join([
|
|
58
59
|
"Context status:",
|
|
59
60
|
f"- tokens: {status.used_tokens}/{status.input_token_limit} ({status.percent:.2f}%)",
|
|
60
|
-
f"- token split base/active_wrappers/
|
|
61
|
+
f"- token split base/vanished_wrappers/active_wrappers/providers: {status.base_context_tokens}/{status.vanished_wrapper_tokens}/{status.active_wrapper_tokens}/{status.provider_context_tokens}",
|
|
61
62
|
f"- messages sent/total: {status.sent_session_messages}/{status.total_session_messages}",
|
|
62
63
|
f"- persistent/temporary context messages: {status.persistent_session_messages}/{status.temporary_session_messages}",
|
|
63
64
|
f"- wrappers active/vanished/total: {status.active_wrapper_messages}/{status.vanished_wrapper_messages}/{status.total_wrapper_messages}",
|
|
@@ -12,6 +12,8 @@ from .utils import runtime_join, text_content
|
|
|
12
12
|
|
|
13
13
|
DEFAULT_SYSTEM_PROMPT_PATH = os.path.join(os.path.dirname(__file__), "prompts", "system_prompt.txt")
|
|
14
14
|
DEFAULT_SYSTEM_PROMPT = text_content(DEFAULT_SYSTEM_PROMPT_PATH)
|
|
15
|
+
DEFAULT_COMPACTION_PROMPT_PATH = os.path.join(os.path.dirname(__file__), "prompts", "compaction_prompt.txt")
|
|
16
|
+
DEFAULT_COMPACTION_PROMPT = text_content(DEFAULT_COMPACTION_PROMPT_PATH)
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
def parse_config_value(value):
|
|
@@ -82,6 +84,7 @@ class AgentConfig(Config):
|
|
|
82
84
|
|
|
83
85
|
model = "gpt-5.4"
|
|
84
86
|
compaction_model = "gpt-5.4-mini"
|
|
87
|
+
compaction_instructions = DEFAULT_COMPACTION_PROMPT
|
|
85
88
|
system = DEFAULT_SYSTEM_PROMPT
|
|
86
89
|
auto_proceed = True
|
|
87
90
|
openai_api_key = None
|
|
@@ -14,6 +14,7 @@ class ContextManager:
|
|
|
14
14
|
def __init__(self, agent):
|
|
15
15
|
self.agent = agent
|
|
16
16
|
self.token_count_coef = 1.0
|
|
17
|
+
self.last_provider_tokens = 0
|
|
17
18
|
|
|
18
19
|
def provider_context_wrapper(self, provider_name, content):
|
|
19
20
|
return f'<context_provider name="{provider_name}">\n{content}\n</context_provider>'
|
|
@@ -85,6 +86,8 @@ class ContextManager:
|
|
|
85
86
|
system = [self.agent.config_manager.system_message()]
|
|
86
87
|
response_tools = self.agent.tools_manager.get_response_tools()
|
|
87
88
|
providers_msgs = self.get_providers_messages()
|
|
89
|
+
provider_tokens = self.response_input_token_count(providers_msgs, response_tools=[])
|
|
90
|
+
self.last_provider_tokens = provider_tokens
|
|
88
91
|
max_images = self.agent.config.get("max_images", 10)
|
|
89
92
|
|
|
90
93
|
if self.agent.config.prune_orphaned_tool_outputs_on_context_build:
|
|
@@ -139,7 +142,7 @@ class ContextManager:
|
|
|
139
142
|
active_context_wrappers = [msg for msg in history if isinstance(msg, ToolResultWrapper)]
|
|
140
143
|
active_wrapper_tokens = wrapper_token_count(active_context_wrappers)
|
|
141
144
|
vanished_wrapper_tokens = wrapper_token_count(vanished_wrappers)
|
|
142
|
-
base_context_tokens = max(0, current_count - active_wrapper_tokens)
|
|
145
|
+
base_context_tokens = max(0, current_count - provider_tokens - active_wrapper_tokens)
|
|
143
146
|
if self.agent.session:
|
|
144
147
|
compaction_plan = self.agent.session.compaction_plan(
|
|
145
148
|
max_input_tokens=max_input_tokens,
|
|
@@ -174,6 +177,7 @@ class ContextManager:
|
|
|
174
177
|
vanished_wrapper_messages=len(vanished_wrappers),
|
|
175
178
|
total_wrapper_messages=len(wrappers),
|
|
176
179
|
base_context_tokens=base_context_tokens,
|
|
180
|
+
provider_context_tokens=provider_tokens,
|
|
177
181
|
active_wrapper_tokens=active_wrapper_tokens,
|
|
178
182
|
vanished_wrapper_tokens=vanished_wrapper_tokens,
|
|
179
183
|
compactable_turns=compactable_turns,
|
|
@@ -259,7 +259,7 @@ class CompactionMessage(DeveloperMessage):
|
|
|
259
259
|
name = "compaction"
|
|
260
260
|
content = "Previous conversation context was compacted by the backend."
|
|
261
261
|
response_id = ""
|
|
262
|
-
|
|
262
|
+
output = modict.factory(list)
|
|
263
263
|
usage = modict.factory(modict)
|
|
264
264
|
compacted_message_count = 0
|
|
265
265
|
|
|
@@ -268,8 +268,12 @@ class CompactionMessage(DeveloperMessage):
|
|
|
268
268
|
super().__init__(*args, **kwargs)
|
|
269
269
|
if output_items is None:
|
|
270
270
|
output_items = self.pop("output_items", None)
|
|
271
|
-
|
|
272
|
-
|
|
271
|
+
legacy_summaries = self.pop("summaries", None)
|
|
272
|
+
if not self.get("output"):
|
|
273
|
+
if output_items is not None:
|
|
274
|
+
self.output = list(output_items or [])
|
|
275
|
+
elif legacy_summaries is not None:
|
|
276
|
+
self.output = list(legacy_summaries or [])
|
|
273
277
|
|
|
274
278
|
@staticmethod
|
|
275
279
|
def summary_items(items):
|
|
@@ -278,8 +282,12 @@ class CompactionMessage(DeveloperMessage):
|
|
|
278
282
|
if item.get("type") == "compaction_summary"
|
|
279
283
|
]
|
|
280
284
|
|
|
285
|
+
@property
|
|
286
|
+
def summaries(self):
|
|
287
|
+
return self.summary_items(self.get("output") or [])
|
|
288
|
+
|
|
281
289
|
def to_response_format(self):
|
|
282
|
-
return list(self.get("
|
|
290
|
+
return list(self.get("output") or [])
|
|
283
291
|
|
|
284
292
|
def observed_token_count(self):
|
|
285
293
|
usage = self.get("usage") or {}
|
|
@@ -306,7 +314,7 @@ class CompactionMessage(DeveloperMessage):
|
|
|
306
314
|
|
|
307
315
|
def token_count_payload(self):
|
|
308
316
|
sanitized = []
|
|
309
|
-
for item in self.get("
|
|
317
|
+
for item in self.get("output") or []:
|
|
310
318
|
entry = dict(item)
|
|
311
319
|
if entry.get("type") == "compaction_summary" and entry.get("encrypted_content"):
|
|
312
320
|
entry["encrypted_content"] = "<encrypted_compaction_summary>"
|
|
@@ -320,17 +328,19 @@ class CompactionMessage(DeveloperMessage):
|
|
|
320
328
|
return self.format_as_string_attrs(attrs)
|
|
321
329
|
|
|
322
330
|
def as_string_body(self):
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
None,
|
|
326
|
-
)
|
|
327
|
-
if not summary:
|
|
331
|
+
summaries = self.summary_items(self.get("output") or [])
|
|
332
|
+
if not summaries:
|
|
328
333
|
return self.content
|
|
334
|
+
summary_lines = "\n".join(
|
|
335
|
+
f"<compaction_summary id={summary.get('id', '')!r}>opaque backend summary</compaction_summary>"
|
|
336
|
+
for summary in summaries
|
|
337
|
+
)
|
|
338
|
+
output_count = len(self.get("output") or [])
|
|
329
339
|
return dedent(
|
|
330
340
|
f"""{self.content}
|
|
331
|
-
<
|
|
332
|
-
|
|
333
|
-
</
|
|
341
|
+
<compaction_output items={output_count}>
|
|
342
|
+
{summary_lines}
|
|
343
|
+
</compaction_output>"""
|
|
334
344
|
)
|
|
335
345
|
|
|
336
346
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
You are the standalone compaction model for an agentic coding assistant conversation.
|
|
2
|
+
|
|
3
|
+
Goal: replace the provided conversation history with the smallest useful compacted history that still lets the agent continue the task safely and coherently.
|
|
4
|
+
|
|
5
|
+
Instructions:
|
|
6
|
+
- Reduce the visible content of each retained message as aggressively as possible.
|
|
7
|
+
- Keep only information that is useful for future continuation: user goals, decisions, constraints, file paths, commands/results that matter, bugs found, fixes applied, validation status, unresolved questions, TODOs, and exact identifiers such as versions, commits, tags, job ids, paths, APIs, function/class names, and error messages.
|
|
8
|
+
- Remove chatter, repeated confirmations, verbose tool output, incidental logs, redundant reasoning, and obsolete branches of investigation.
|
|
9
|
+
- Preserve chronology and causality when it affects future decisions.
|
|
10
|
+
- The history to compact will often begin with output from a previous compaction. Treat that previous compacted context as important long-range background: carry forward its still-relevant facts, decisions, constraints, unresolved TODOs, and exact identifiers into the new final compaction, further compressed if needed, so repeated compactions keep a durable trace of distant context instead of replacing it with only the newest turns.
|
|
11
|
+
- Preserve the distinction between facts observed from tools/source-of-truth and inferences or hypotheses.
|
|
12
|
+
- Do not invent missing facts. If something is uncertain, mark it as uncertain.
|
|
13
|
+
- If tool outputs were summarized, keep the actionable conclusions and any exact values needed later, not the full raw output.
|
|
14
|
+
- The encrypted compaction summary should be dense, explicit, and highly informative. It must help the agent resume without relying on external memory/RAG.
|
|
15
|
+
- Prefer compact bullet-like factual wording over prose.
|
|
16
|
+
|
|
17
|
+
Return the compacted output in the format required by the compaction endpoint.
|
|
@@ -183,7 +183,7 @@ class AgentSession(modict):
|
|
|
183
183
|
usage = dict(usage)
|
|
184
184
|
message = CompactionMessage(
|
|
185
185
|
response_id=result.id,
|
|
186
|
-
|
|
186
|
+
output=list(result.output or []),
|
|
187
187
|
usage=usage or {},
|
|
188
188
|
compacted_message_count=len(compacted_messages),
|
|
189
189
|
compacted_turn_count=plan.compacted_turn_count,
|
|
@@ -832,6 +832,8 @@ class SessionsManager:
|
|
|
832
832
|
model=model,
|
|
833
833
|
max_input_tokens=max_input_tokens,
|
|
834
834
|
)
|
|
835
|
+
if instructions is None:
|
|
836
|
+
instructions = self.agent.config.get("compaction_instructions")
|
|
835
837
|
if instructions is not None:
|
|
836
838
|
compact_kwargs.instructions = instructions
|
|
837
839
|
if max_compacted_turns is not None:
|
|
@@ -33,6 +33,7 @@ class StatusManager:
|
|
|
33
33
|
vanished_wrapper_messages=context_status.get("vanished_wrapper_messages", 0),
|
|
34
34
|
total_wrapper_messages=context_status.get("total_wrapper_messages", 0),
|
|
35
35
|
base_context_tokens=context_status.get("base_context_tokens", context_status.used_tokens),
|
|
36
|
+
provider_context_tokens=context_status.get("provider_context_tokens", 0),
|
|
36
37
|
active_wrapper_tokens=context_status.get("active_wrapper_tokens", 0),
|
|
37
38
|
vanished_wrapper_tokens=context_status.get("vanished_wrapper_tokens", 0),
|
|
38
39
|
compactable_turns=context_status.get("compactable_turns", 0),
|
|
@@ -89,8 +90,9 @@ class StatusManager:
|
|
|
89
90
|
msg_copy.content = truncate(msg_copy.content, max_tokens=max_input_tokens, model=self.agent.config.model)
|
|
90
91
|
truncated_others.append(msg_copy)
|
|
91
92
|
|
|
93
|
+
provider_tokens = int(getattr(context_manager, "last_provider_tokens", 0) or 0)
|
|
92
94
|
fixed_tokens = context_manager.response_input_token_count(system + images, response_tools=response_tools)
|
|
93
|
-
current_count = fixed_tokens
|
|
95
|
+
current_count = fixed_tokens + provider_tokens
|
|
94
96
|
history_start = len(truncated_others)
|
|
95
97
|
for i, msg in enumerate(reversed(truncated_others)):
|
|
96
98
|
msg_count = context_manager.response_input_token_count([msg], response_tools=[])
|
|
@@ -131,7 +133,7 @@ class StatusManager:
|
|
|
131
133
|
active_context_wrappers = [msg for msg in included_others if isinstance(msg, ToolResultWrapper)]
|
|
132
134
|
active_wrapper_tokens = wrapper_token_count(active_context_wrappers)
|
|
133
135
|
vanished_wrapper_tokens = wrapper_token_count(vanished_wrappers)
|
|
134
|
-
base_context_tokens = max(0, current_count - active_wrapper_tokens)
|
|
136
|
+
base_context_tokens = max(0, current_count - provider_tokens - active_wrapper_tokens)
|
|
135
137
|
if self.agent.session:
|
|
136
138
|
compaction_plan = self.agent.session.compaction_plan(
|
|
137
139
|
max_input_tokens=max_input_tokens,
|
|
@@ -151,6 +153,7 @@ class StatusManager:
|
|
|
151
153
|
input_token_limit=input_limit,
|
|
152
154
|
percent=percent,
|
|
153
155
|
fixed_tokens=fixed_tokens,
|
|
156
|
+
provider_context_tokens=provider_tokens,
|
|
154
157
|
tool_spec_tokens=context_manager.response_tools_token_count(response_tools),
|
|
155
158
|
token_count_source="local_estimate",
|
|
156
159
|
visible_history_messages=visible_history_count,
|
|
@@ -213,6 +216,7 @@ class StatusManager:
|
|
|
213
216
|
vanished_wrapper_messages=estimated.get("vanished_wrapper_messages", 0),
|
|
214
217
|
total_wrapper_messages=estimated.get("total_wrapper_messages", 0),
|
|
215
218
|
base_context_tokens=estimated.get("base_context_tokens", estimated.used_tokens),
|
|
219
|
+
provider_context_tokens=estimated.get("provider_context_tokens", 0),
|
|
216
220
|
active_wrapper_tokens=estimated.get("active_wrapper_tokens", 0),
|
|
217
221
|
vanished_wrapper_tokens=estimated.get("vanished_wrapper_tokens", 0),
|
|
218
222
|
compactable_turns=estimated.get("compactable_turns", 0),
|
|
@@ -247,6 +251,7 @@ class StatusManager:
|
|
|
247
251
|
vanished_wrapper_messages=estimated.get("vanished_wrapper_messages", 0),
|
|
248
252
|
total_wrapper_messages=estimated.get("total_wrapper_messages", 0),
|
|
249
253
|
base_context_tokens=estimated.get("base_context_tokens", estimated.used_tokens),
|
|
254
|
+
provider_context_tokens=estimated.get("provider_context_tokens", 0),
|
|
250
255
|
active_wrapper_tokens=estimated.get("active_wrapper_tokens", 0),
|
|
251
256
|
vanished_wrapper_tokens=estimated.get("vanished_wrapper_tokens", 0),
|
|
252
257
|
compactable_turns=estimated.get("compactable_turns", 0),
|
|
@@ -282,7 +287,8 @@ class StatusManager:
|
|
|
282
287
|
active_wrapper_messages=context_status.get("active_wrapper_messages", 0),
|
|
283
288
|
vanished_wrapper_messages=context_status.get("vanished_wrapper_messages", 0),
|
|
284
289
|
total_wrapper_messages=context_status.get("total_wrapper_messages", 0),
|
|
285
|
-
base_context_tokens=max(0, input_tokens - context_status.get("active_wrapper_tokens", 0)),
|
|
290
|
+
base_context_tokens=max(0, input_tokens - context_status.get("provider_context_tokens", 0) - context_status.get("active_wrapper_tokens", 0)),
|
|
291
|
+
provider_context_tokens=context_status.get("provider_context_tokens", 0),
|
|
286
292
|
active_wrapper_tokens=context_status.get("active_wrapper_tokens", 0),
|
|
287
293
|
vanished_wrapper_tokens=context_status.get("vanished_wrapper_tokens", 0),
|
|
288
294
|
compactable_turns=context_status.get("compactable_turns", 0),
|
|
@@ -26,25 +26,50 @@ class StatusBar:
|
|
|
26
26
|
|
|
27
27
|
@classmethod
|
|
28
28
|
def _context_token_segments(cls, status, used, limit):
|
|
29
|
-
if
|
|
29
|
+
if (
|
|
30
|
+
"base_context_tokens" not in status
|
|
31
|
+
and "provider_context_tokens" not in status
|
|
32
|
+
and "active_wrapper_tokens" not in status
|
|
33
|
+
and "vanished_wrapper_tokens" not in status
|
|
34
|
+
):
|
|
30
35
|
return ((f"{used}/{limit} ktok", "#8b949e on #161b22"),)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
base_tokens = status.get("base_context_tokens") or 0
|
|
37
|
+
provider_tokens = status.get("provider_context_tokens") or 0
|
|
38
|
+
active_wrapper_tokens = status.get("active_wrapper_tokens") or 0
|
|
39
|
+
vanished_wrapper_tokens = status.get("vanished_wrapper_tokens") or 0
|
|
40
|
+
active_total = cls._format_ktok(base_tokens + provider_tokens + active_wrapper_tokens)
|
|
41
|
+
segments = [
|
|
42
|
+
(cls._format_ktok(base_tokens), "#c9d1d9 on #161b22"),
|
|
43
|
+
]
|
|
44
|
+
segments.extend([
|
|
45
|
+
(f"(+{cls._format_ktok(vanished_wrapper_tokens)})", "italic #6e7681 on #161b22"),
|
|
46
|
+
(f"+{cls._format_ktok(active_wrapper_tokens)}", "italic #f0883e on #161b22"),
|
|
47
|
+
])
|
|
48
|
+
if provider_tokens:
|
|
49
|
+
segments.append((f"+{cls._format_ktok(provider_tokens)}", "italic #58a6ff on #161b22"))
|
|
50
|
+
segments.extend([
|
|
51
|
+
("=", "#8b949e on #161b22"),
|
|
52
|
+
(active_total, "#c9d1d9 on #161b22"),
|
|
35
53
|
(f"/{limit} ktok", "#8b949e on #161b22"),
|
|
36
|
-
)
|
|
54
|
+
])
|
|
55
|
+
return tuple(segments)
|
|
37
56
|
|
|
38
57
|
@classmethod
|
|
39
58
|
def _message_segments(cls, status):
|
|
40
59
|
sent = int(status.get("sent_session_messages") or 0)
|
|
41
60
|
total = int(status.get("total_session_messages") or 0)
|
|
42
61
|
if "active_wrapper_messages" in status or "vanished_wrapper_messages" in status:
|
|
62
|
+
persistent = int(status.get("persistent_session_messages") or 0)
|
|
63
|
+
active_wrappers = int(status.get("active_wrapper_messages") or 0)
|
|
64
|
+
vanished_wrappers = int(status.get("vanished_wrapper_messages") or 0)
|
|
65
|
+
active_total = persistent + active_wrappers
|
|
43
66
|
return (
|
|
44
|
-
(str(
|
|
45
|
-
(f"+{
|
|
46
|
-
(f"+{
|
|
47
|
-
(
|
|
67
|
+
(str(persistent), "#c9d1d9 on #161b22"),
|
|
68
|
+
(f"(+{vanished_wrappers})", "italic #6e7681 on #161b22"),
|
|
69
|
+
(f"+{active_wrappers}", "italic #f0883e on #161b22"),
|
|
70
|
+
("=", "#8b949e on #161b22"),
|
|
71
|
+
(str(active_total), "#c9d1d9 on #161b22"),
|
|
72
|
+
(f"/{total}", "#8b949e on #161b22"),
|
|
48
73
|
)
|
|
49
74
|
if "persistent_session_messages" in status or "temporary_session_messages" in status:
|
|
50
75
|
return (
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.61"
|
|
@@ -89,6 +89,7 @@ codex_agent/get_text/__init__.py
|
|
|
89
89
|
codex_agent/get_text/default_gitignore
|
|
90
90
|
codex_agent/get_text/get_text.py
|
|
91
91
|
codex_agent/get_text/simpler_get_text.py
|
|
92
|
+
codex_agent/prompts/compaction_prompt.txt
|
|
92
93
|
codex_agent/prompts/system_prompt.txt
|
|
93
94
|
codex_agent/scripts/install-system-dependencies.sh
|
|
94
95
|
codex_agent/server/__init__.py
|
|
@@ -103,7 +103,10 @@ def test_agent_session_compact_purges_compacted_prefix_before_remainder(tmp_path
|
|
|
103
103
|
assert session.messages == [message, current]
|
|
104
104
|
assert [msg.id for msg in AgentSession.load(session.session_id).messages] == [message.id, current.id]
|
|
105
105
|
assert "output_items" not in message
|
|
106
|
+
assert "summaries" not in message
|
|
107
|
+
assert message.output == FakeCompactionResult.output
|
|
106
108
|
assert message.summaries == [FakeCompactionResult.output[1]]
|
|
109
|
+
assert message.to_response_format() == FakeCompactionResult.output
|
|
107
110
|
assert message.usage == FakeCompactionResult.usage
|
|
108
111
|
assert message.count_tokens(model="gpt-5") == 12000
|
|
109
112
|
assert message.compacted_message_count == 2
|
|
@@ -358,7 +361,7 @@ def test_agent_get_response_auto_compact_failure_continues_backend_call(monkeypa
|
|
|
358
361
|
assert not any(isinstance(message, CompactionMessage) for message in agent.session.messages)
|
|
359
362
|
|
|
360
363
|
|
|
361
|
-
def
|
|
364
|
+
def test_agent_compact_session_uses_mini_model_and_instructions_by_default():
|
|
362
365
|
agent = Agent(session="new")
|
|
363
366
|
visible = DeveloperMessage(content="visible compactable context")
|
|
364
367
|
done = AssistantMessage(content="done")
|
|
@@ -370,7 +373,8 @@ def test_agent_compact_session_uses_mini_model_by_default():
|
|
|
370
373
|
|
|
371
374
|
assert isinstance(message, CompactionMessage)
|
|
372
375
|
assert client.params["model"] == "gpt-5.4-mini"
|
|
373
|
-
assert "
|
|
376
|
+
assert "smallest useful compacted history" in client.params["instructions"]
|
|
377
|
+
assert "encrypted compaction summary" in client.params["instructions"]
|
|
374
378
|
|
|
375
379
|
|
|
376
380
|
def test_agent_compact_session_respects_explicit_model_override():
|
|
@@ -401,6 +405,21 @@ def test_agent_compact_session_respects_explicit_instructions_override():
|
|
|
401
405
|
assert client.params["instructions"] == "Summarize faithfully."
|
|
402
406
|
|
|
403
407
|
|
|
408
|
+
def test_agent_compact_session_can_disable_default_instructions():
|
|
409
|
+
agent = Agent(session="new")
|
|
410
|
+
agent.config.compaction_instructions = None
|
|
411
|
+
visible = DeveloperMessage(content="visible compactable context")
|
|
412
|
+
done = AssistantMessage(content="done")
|
|
413
|
+
current = DeveloperMessage(content="current unfinished turn")
|
|
414
|
+
agent.session.messages = [visible, done, current]
|
|
415
|
+
client = FakeCompactionClient()
|
|
416
|
+
|
|
417
|
+
message = agent.compact_session(client=client)
|
|
418
|
+
|
|
419
|
+
assert isinstance(message, CompactionMessage)
|
|
420
|
+
assert "instructions" not in client.params
|
|
421
|
+
|
|
422
|
+
|
|
404
423
|
def test_slash_compact_reports_compaction_failure(monkeypatch):
|
|
405
424
|
agent = Agent(session="new")
|
|
406
425
|
monkeypatch.setattr(agent, "compact_session", lambda **_kwargs: modict(status="failed", error="boom"))
|
|
@@ -472,18 +491,24 @@ def test_agent_tool_result_messages_append_directly_without_pending():
|
|
|
472
491
|
def test_agent_get_context_starts_at_latest_compaction():
|
|
473
492
|
agent = Agent(session="new")
|
|
474
493
|
old = DeveloperMessage(content="old hidden context")
|
|
475
|
-
|
|
494
|
+
previous_output = [
|
|
495
|
+
{"type": "message", "role": "developer", "content": [{"type": "input_text", "text": "compacted visible anchor"}]},
|
|
496
|
+
{"type": "compaction_summary", "id": "cs_123", "encrypted_content": "opaque"},
|
|
497
|
+
]
|
|
498
|
+
previous = CompactionMessage(output=previous_output)
|
|
476
499
|
current = DeveloperMessage(content="current visible context")
|
|
477
500
|
agent.session.messages = [old, previous, current]
|
|
478
501
|
|
|
479
502
|
context = agent.context_manager.get_context()
|
|
480
503
|
context_text = "\n".join(str(message.get("content", "")) for message in context)
|
|
504
|
+
payload = agent.context_manager.response_input_token_payload(context)
|
|
481
505
|
|
|
482
506
|
context_ids = [message.id for message in context]
|
|
483
507
|
assert previous.id in context_ids
|
|
484
508
|
assert current.id in context_ids
|
|
485
509
|
assert old.id not in context_ids
|
|
486
510
|
assert "old hidden context" not in context_text
|
|
511
|
+
assert payload.input[:2] == previous_output
|
|
487
512
|
|
|
488
513
|
|
|
489
514
|
def test_agent_local_context_estimate_does_not_count_encrypted_compaction_payload():
|
|
@@ -387,6 +387,7 @@ def test_context_plugin_exposes_monitor_control_tools_and_wrapper_pruning():
|
|
|
387
387
|
assert status.temporary_session_messages >= 3
|
|
388
388
|
monitor = agent.providers.context_status_monitor()
|
|
389
389
|
assert "Context status:" in monitor
|
|
390
|
+
assert "token split base/vanished_wrappers/active_wrappers/providers" in monitor
|
|
390
391
|
assert "context_prune_wrappers" in monitor
|
|
391
392
|
|
|
392
393
|
wrappers = agent.tools.context_list_wrappers()
|
|
@@ -204,6 +204,7 @@ def test_agent_get_response_auto_compacts_before_backend_call(monkeypatch):
|
|
|
204
204
|
assert calls == [{
|
|
205
205
|
"model": agent.config.compaction_model,
|
|
206
206
|
"max_input_tokens": agent.config.max_input_tokens,
|
|
207
|
+
"instructions": agent.config.compaction_instructions,
|
|
207
208
|
}]
|
|
208
209
|
assert any(isinstance(message, CompactionMessage) for message in agent.ai.params["messages"])
|
|
209
210
|
|
|
@@ -285,7 +285,22 @@ def test_agent_context_status_counts_active_and_vanished_wrappers():
|
|
|
285
285
|
assert status.active_wrapper_tokens > 0
|
|
286
286
|
assert status.vanished_wrapper_tokens > 0
|
|
287
287
|
assert status.base_context_tokens >= status.fixed_tokens
|
|
288
|
-
assert status.
|
|
288
|
+
assert status.provider_context_tokens == 0
|
|
289
|
+
assert status.used_tokens == status.base_context_tokens + status.provider_context_tokens + status.active_wrapper_tokens
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def test_agent_context_status_reuses_last_provider_tokens_in_visible_total():
|
|
293
|
+
agent = Agent(session="new", input_token_limit=10_000)
|
|
294
|
+
agent.context_manager.last_provider_tokens = 1_234
|
|
295
|
+
agent.session.messages = [DeveloperMessage(content="persistent context")]
|
|
296
|
+
|
|
297
|
+
status = agent.status_manager.context_status()
|
|
298
|
+
|
|
299
|
+
assert status.provider_context_tokens == 1_234
|
|
300
|
+
assert status.vanished_wrapper_tokens >= 0
|
|
301
|
+
assert status.used_tokens == status.base_context_tokens + status.provider_context_tokens + status.active_wrapper_tokens
|
|
302
|
+
assert status.used_tokens < status.base_context_tokens + status.provider_context_tokens + status.active_wrapper_tokens + status.vanished_wrapper_tokens or status.vanished_wrapper_tokens == 0
|
|
303
|
+
assert status.percent == status.used_tokens / 10_000 * 100
|
|
289
304
|
|
|
290
305
|
|
|
291
306
|
def test_agent_status_preserves_persistent_and_temporary_message_counts():
|
|
@@ -557,6 +572,7 @@ def test_chat_status_bar_formats_context_and_message_wrapper_splits():
|
|
|
557
572
|
context_limit_tokens=128_000,
|
|
558
573
|
context_percent=9.609,
|
|
559
574
|
base_context_tokens=10_000,
|
|
575
|
+
provider_context_tokens=3_000,
|
|
560
576
|
active_wrapper_tokens=2_000,
|
|
561
577
|
vanished_wrapper_tokens=4_000,
|
|
562
578
|
sent_session_messages=43,
|
|
@@ -574,15 +590,15 @@ def test_chat_status_bar_formats_context_and_message_wrapper_splits():
|
|
|
574
590
|
rendered = StatusBar.render(status)
|
|
575
591
|
output = rendered.plain
|
|
576
592
|
|
|
577
|
-
assert "ctx 10.0+2.0+
|
|
578
|
-
assert "msg 33+7
|
|
593
|
+
assert "ctx 10.0(+4.0)+2.0+3.0=15.0/128.0 ktok" in output
|
|
594
|
+
assert "msg 33(+12)+7=40/93" in output
|
|
579
595
|
assert "cmp 17" in output
|
|
580
596
|
assert any(
|
|
581
597
|
"#f0883e" in str(span.style) and output[span.start:span.end] in {"+2.0", "+7"}
|
|
582
598
|
for span in rendered.spans
|
|
583
599
|
)
|
|
584
600
|
assert any(
|
|
585
|
-
"#6e7681" in str(span.style) and output[span.start:span.end] in {"+4.0", "+12"}
|
|
601
|
+
"#6e7681" in str(span.style) and output[span.start:span.end] in {"(+4.0)", "(+12)"}
|
|
586
602
|
for span in rendered.spans
|
|
587
603
|
)
|
|
588
604
|
|
|
@@ -214,18 +214,19 @@ def test_server_tool_response_message_as_string_includes_item_metadata():
|
|
|
214
214
|
assert '"type": "web_search_call"' in text
|
|
215
215
|
|
|
216
216
|
|
|
217
|
-
def
|
|
218
|
-
|
|
217
|
+
def test_compaction_message_replays_full_backend_output():
|
|
218
|
+
output = [
|
|
219
219
|
{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "old"}]},
|
|
220
220
|
{"type": "compaction_summary", "id": "cs_123", "encrypted_content": "opaque"},
|
|
221
221
|
]
|
|
222
222
|
message = CompactionMessage(
|
|
223
223
|
response_id="resp_123",
|
|
224
|
-
|
|
224
|
+
output=output,
|
|
225
225
|
compacted_message_count=4,
|
|
226
226
|
)
|
|
227
227
|
|
|
228
|
-
assert message.to_response_format() ==
|
|
228
|
+
assert message.to_response_format() == output
|
|
229
|
+
assert message.summaries == [output[1]]
|
|
229
230
|
text = message.as_string()
|
|
230
231
|
assert text.startswith("<CompactionMessage ")
|
|
231
232
|
assert "response_id='resp_123'" in text
|
|
@@ -244,13 +245,14 @@ def test_compaction_message_migrates_legacy_output_items_without_persisting_them
|
|
|
244
245
|
message = CompactionMessage({"output_items": output_items})
|
|
245
246
|
|
|
246
247
|
assert "output_items" not in message
|
|
248
|
+
assert message.output == output_items
|
|
247
249
|
assert message.summaries == [output_items[1]]
|
|
248
|
-
assert message.to_response_format() ==
|
|
250
|
+
assert message.to_response_format() == output_items
|
|
249
251
|
|
|
250
252
|
|
|
251
253
|
def test_compaction_message_prefers_output_usage_token_count():
|
|
252
254
|
message = CompactionMessage(
|
|
253
|
-
|
|
255
|
+
output=[{"type": "compaction_summary", "id": "cs_123", "encrypted_content": "opaque"}],
|
|
254
256
|
usage={"input_tokens": 42897, "output_tokens": 12000, "total_tokens": 54912},
|
|
255
257
|
)
|
|
256
258
|
|
|
@@ -260,7 +262,7 @@ def test_compaction_message_prefers_output_usage_token_count():
|
|
|
260
262
|
|
|
261
263
|
def test_compaction_message_ignores_input_usage_as_future_context_size():
|
|
262
264
|
message = CompactionMessage(
|
|
263
|
-
|
|
265
|
+
output=[{"type": "compaction_summary", "id": "cs_123", "encrypted_content": "opaque"}],
|
|
264
266
|
usage={"input_tokens": 50000, "max_input_tokens": 60000},
|
|
265
267
|
)
|
|
266
268
|
|
|
@@ -147,7 +147,7 @@ def test_token_counter_prefers_observed_usage_for_compaction_message():
|
|
|
147
147
|
ai = FakeAI()
|
|
148
148
|
counter = TokenCounter(ai, default_model="gpt-5")
|
|
149
149
|
message = CompactionMessage(
|
|
150
|
-
|
|
150
|
+
output=[{"type": "compaction_summary", "id": "cs_123", "encrypted_content": "opaque"}],
|
|
151
151
|
usage={"input_tokens": 400, "output_tokens": 120, "total_tokens": 520},
|
|
152
152
|
)
|
|
153
153
|
|
|
@@ -162,7 +162,8 @@ def test_token_counter_falls_back_to_compaction_request_when_no_observed_usage()
|
|
|
162
162
|
ai = FakeAI()
|
|
163
163
|
counter = TokenCounter(ai, default_model="gpt-5")
|
|
164
164
|
message = CompactionMessage(
|
|
165
|
-
|
|
165
|
+
output=[{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "old"}]},
|
|
166
|
+
{"type": "compaction_summary", "id": "cs_123", "encrypted_content": "opaque"}],
|
|
166
167
|
)
|
|
167
168
|
|
|
168
169
|
count = counter.count_object(message)
|
|
@@ -170,11 +171,14 @@ def test_token_counter_falls_back_to_compaction_request_when_no_observed_usage()
|
|
|
170
171
|
assert count == 303
|
|
171
172
|
assert ai.calls == [{
|
|
172
173
|
"model": "gpt-5",
|
|
173
|
-
"input": [
|
|
174
|
-
"type": "
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
174
|
+
"input": [
|
|
175
|
+
{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "old"}]},
|
|
176
|
+
{
|
|
177
|
+
"type": "compaction_summary",
|
|
178
|
+
"id": "cs_123",
|
|
179
|
+
"encrypted_content": "<encrypted_compaction_summary>",
|
|
180
|
+
},
|
|
181
|
+
],
|
|
178
182
|
}]
|
|
179
183
|
assert message.token_count["gpt-5"]["count"] == 303
|
|
180
184
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.60"
|
|
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.60 → codex_agent_framework-0.1.61}/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
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/get_text/__init__.py
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/codex_agent/get_text/default_gitignore
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/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
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/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.60 → codex_agent_framework-0.1.61}/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.60 → codex_agent_framework-0.1.61}/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.60 → codex_agent_framework-0.1.61}/tests/test_agent_audio_hooks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_environment.py
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/tests/test_agent_image_generation.py
RENAMED
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/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
|
{codex_agent_framework-0.1.60 → codex_agent_framework-0.1.61}/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
|
|
File without changes
|