Navi Code: force context compression via typed /compact control message
...
Forced /compact previously sent a chat message, which ran a full agent turn
that only produced summary text instead of running the real context compressor.
Worse, even when wired correctly, forced compact always reported "Nothing to
compact yet — the context is still small" regardless of context size: the typical
navi_code shape is a single long autonomous turn (1 user message + many tool
iterations = one turn), and partition_messages finds nothing to summarize when
turns <= keep_recent. The midturn auto-compress path already bypassed this via
keep_recent_messages (intra-turn split), but compact_stream passed
keep_recent_messages=None, so the fallback was disabled.
Changes:
- WS protocol: {"type":"compact"} control message (distinct from {"type":
"message"}); rejected while an agent turn is active to avoid racing the agent.
- Agent.compact_stream: forced compression that bypasses the token threshold
but still runs the real compressor; passes keep_recent_messages=max(12,
context_keep_recent*2) so a single long turn compresses via intra-turn split
(mirrors midturn auto-compress). Raises NothingToCompactError when context is
genuinely too small.
- Orchestrator.run_compact + clear_run: broadcast agent events to subscribers,
end with done marker, surface NothingToCompactError as an error event.
- Terminal client: ws_client.send accepts str|dict; CompactCommand enqueues
{"type":"compact"}; TUI distinguishes forced compact (no stream_start) from
in-turn auto-compress via the _streaming flag.
- Tests: compact_stream (incl. single-long-turn regression), WS handler
dispatch/rejection, run_compact event/error broadcasting, ws_client send,
compact command.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
20 hours ago