chore: import upstream snapshot with attribution
Deploy Site / deploy-vercel (push) Has been skipped
Deploy Site / deploy-docs (push) Has been skipped
Build Skills Index / build-index (push) Has been skipped
CI / Deny unrelated histories (push) Has been skipped
CI / Detect affected areas (push) Successful in 27m35s
CI / OSV scan (push) Failing after 4s
CI / Build&Test Docker image (push) Successful in 9s
CI / Supply-chain scan (push) Has been skipped
CI / Lint Docker scripts (push) Failing after 5m13s
CI / Check contributors (push) Failing after 12m8s
CI / Docs Site (push) Failing after 12m8s
CI / TypeScript (push) Failing after 12m8s
CI / Python lints (push) Failing after 12m9s
CI / Python tests (push) Failing after 12m9s
CI / Check uv.lock (push) Failing after 23m22s
CI / CI timing report (push) Has been cancelled
Build Skills Index / trigger-deploy (push) Has been cancelled
CI / All required checks pass (push) Has been cancelled
Deploy Site / deploy-vercel (push) Has been skipped
Deploy Site / deploy-docs (push) Has been skipped
Build Skills Index / build-index (push) Has been skipped
CI / Deny unrelated histories (push) Has been skipped
CI / Detect affected areas (push) Successful in 27m35s
CI / OSV scan (push) Failing after 4s
CI / Build&Test Docker image (push) Successful in 9s
CI / Supply-chain scan (push) Has been skipped
CI / Lint Docker scripts (push) Failing after 5m13s
CI / Check contributors (push) Failing after 12m8s
CI / Docs Site (push) Failing after 12m8s
CI / TypeScript (push) Failing after 12m8s
CI / Python lints (push) Failing after 12m9s
CI / Python tests (push) Failing after 12m9s
CI / Check uv.lock (push) Failing after 23m22s
CI / CI timing report (push) Has been cancelled
Build Skills Index / trigger-deploy (push) Has been cancelled
CI / All required checks pass (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from agent.codex_runtime import _record_codex_app_server_compaction
|
||||
from agent.conversation_compression import COMPACTION_STATUS, compress_context
|
||||
from agent.transports.codex_app_server_session import TurnResult
|
||||
|
||||
|
||||
class FakeCodexSession:
|
||||
def __init__(self, result):
|
||||
self.result = result
|
||||
self.calls = 0
|
||||
self.closed = False
|
||||
|
||||
def compact_thread(self):
|
||||
self.calls += 1
|
||||
return self.result
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
|
||||
|
||||
class DummyAgent:
|
||||
def __init__(
|
||||
self,
|
||||
result,
|
||||
*,
|
||||
auto_compaction="native",
|
||||
):
|
||||
self.api_mode = "codex_app_server"
|
||||
self.codex_app_server_auto_compaction = auto_compaction
|
||||
self.session_id = "hermes-session-1"
|
||||
self.platform = "cli"
|
||||
self._cached_system_prompt = "cached prompt"
|
||||
self._codex_session = FakeCodexSession(result)
|
||||
self.context_compressor = SimpleNamespace(
|
||||
compression_count=0,
|
||||
last_compression_rough_tokens=0,
|
||||
last_prompt_tokens=123,
|
||||
last_completion_tokens=45,
|
||||
awaiting_real_usage_after_compression=False,
|
||||
)
|
||||
self.statuses = []
|
||||
self.warnings = []
|
||||
self.events = []
|
||||
self.built_prompts = []
|
||||
|
||||
def _emit_status(self, message):
|
||||
self.statuses.append(message)
|
||||
|
||||
def _emit_warning(self, message):
|
||||
self.warnings.append(message)
|
||||
|
||||
def _build_system_prompt(self, system_message):
|
||||
self.built_prompts.append(system_message)
|
||||
return "built prompt"
|
||||
|
||||
def event_callback(self, name, payload):
|
||||
self.events.append((name, payload))
|
||||
|
||||
|
||||
def test_codex_app_server_native_auto_mode_leaves_thread_compaction_to_codex():
|
||||
agent = DummyAgent(
|
||||
TurnResult(thread_id="thread-1", turn_id="compact-turn-1")
|
||||
)
|
||||
messages = [{"role": "user", "content": "hi"}]
|
||||
|
||||
returned, prompt = compress_context(
|
||||
agent,
|
||||
messages,
|
||||
"system",
|
||||
approx_tokens=100000,
|
||||
task_id="test",
|
||||
)
|
||||
|
||||
assert returned is messages
|
||||
assert prompt == "cached prompt"
|
||||
assert agent._codex_session.calls == 0
|
||||
assert agent.context_compressor.compression_count == 0
|
||||
assert agent.events == []
|
||||
|
||||
|
||||
def test_codex_app_server_manual_compression_routes_to_codex_thread():
|
||||
agent = DummyAgent(
|
||||
TurnResult(thread_id="thread-1", turn_id="compact-turn-1")
|
||||
)
|
||||
messages = [
|
||||
{"role": "user", "content": "hi"},
|
||||
{"role": "assistant", "content": "hello"},
|
||||
]
|
||||
|
||||
returned, prompt = compress_context(
|
||||
agent,
|
||||
messages,
|
||||
"system",
|
||||
approx_tokens=100000,
|
||||
task_id="test",
|
||||
force=True,
|
||||
)
|
||||
|
||||
assert returned is messages
|
||||
assert prompt == "cached prompt"
|
||||
assert agent._codex_session.calls == 1
|
||||
assert agent.context_compressor.compression_count == 1
|
||||
assert agent.context_compressor.last_compression_rough_tokens == 100000
|
||||
# This minimal fake compressor does not implement update_from_response(),
|
||||
# so the runtime preserves its existing pending-usage bookkeeping here.
|
||||
assert agent.context_compressor.last_prompt_tokens == -1
|
||||
assert agent.context_compressor.last_completion_tokens == 0
|
||||
assert agent.context_compressor.awaiting_real_usage_after_compression is True
|
||||
assert agent.events == [
|
||||
(
|
||||
"session:compress",
|
||||
{
|
||||
"platform": "cli",
|
||||
"session_id": "hermes-session-1",
|
||||
"old_session_id": "",
|
||||
"in_place": False,
|
||||
"compression_count": 1,
|
||||
"runtime": "codex_app_server",
|
||||
"thread_id": "thread-1",
|
||||
"turn_id": "compact-turn-1",
|
||||
},
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def test_codex_app_server_hermes_mode_auto_compression_routes_to_codex_thread():
|
||||
agent = DummyAgent(
|
||||
TurnResult(thread_id="thread-1", turn_id="compact-turn-1"),
|
||||
auto_compaction="hermes",
|
||||
)
|
||||
messages = [{"role": "user", "content": "hi"}]
|
||||
|
||||
returned, prompt = compress_context(
|
||||
agent,
|
||||
messages,
|
||||
"system",
|
||||
approx_tokens=100000,
|
||||
)
|
||||
|
||||
assert returned is messages
|
||||
assert prompt == "cached prompt"
|
||||
assert agent._codex_session.calls == 1
|
||||
assert agent.context_compressor.compression_count == 1
|
||||
|
||||
|
||||
def test_codex_app_server_compression_failure_preserves_bookkeeping():
|
||||
agent = DummyAgent(TurnResult(error="compact failed"))
|
||||
messages = [{"role": "user", "content": "hi"}]
|
||||
|
||||
returned, prompt = compress_context(
|
||||
agent,
|
||||
messages,
|
||||
"system",
|
||||
approx_tokens=100000,
|
||||
force=True,
|
||||
)
|
||||
|
||||
assert returned is messages
|
||||
assert prompt == "cached prompt"
|
||||
assert agent._codex_session.calls == 1
|
||||
assert agent.context_compressor.compression_count == 0
|
||||
assert agent.context_compressor.last_prompt_tokens == 123
|
||||
assert agent.warnings
|
||||
|
||||
|
||||
def test_codex_app_server_native_compaction_notice_emits_status_and_event():
|
||||
agent = DummyAgent(
|
||||
TurnResult(thread_id="thread-1", turn_id="normal-turn-1")
|
||||
)
|
||||
turn = TurnResult(
|
||||
thread_id="thread-1",
|
||||
turn_id="normal-turn-1",
|
||||
compacted=True,
|
||||
)
|
||||
|
||||
recorded = _record_codex_app_server_compaction(agent, turn)
|
||||
|
||||
assert recorded is True
|
||||
assert agent.context_compressor.compression_count == 1
|
||||
assert agent.statuses == [COMPACTION_STATUS]
|
||||
assert agent.events == [
|
||||
(
|
||||
"session:compress",
|
||||
{
|
||||
"platform": "cli",
|
||||
"session_id": "hermes-session-1",
|
||||
"old_session_id": "",
|
||||
"in_place": False,
|
||||
"compression_count": 1,
|
||||
"runtime": "codex_app_server",
|
||||
"thread_id": "thread-1",
|
||||
"turn_id": "normal-turn-1",
|
||||
},
|
||||
)
|
||||
]
|
||||
Reference in New Issue
Block a user