from __future__ import annotations import pytest from tests.conftest import build_test_agent_loop, build_test_vibe_config from tests.mock.utils import mock_llm_chunk from tests.stubs.fake_backend import FakeBackend from vibe.core.types import ( AssistantEvent, CompactEndEvent, CompactStartEvent, LLMMessage, Role, UserMessageEvent, ) @pytest.mark.asyncio async def test_auto_compact_triggers_and_batches_observer( telemetry_events: list[dict], ) -> None: observed: list[tuple[Role, str | None]] = [] def observer(msg: LLMMessage) -> None: observed.append((msg.role, msg.content)) backend = FakeBackend([ [mock_llm_chunk(content="")], [mock_llm_chunk(content="")], ]) cfg = build_test_vibe_config(auto_compact_threshold=1) agent = build_test_agent_loop( config=cfg, message_observer=observer, backend=backend ) agent.stats.context_tokens = 2 events = [ev async for ev in agent.act("Hello")] assert len(events) == 4 assert isinstance(events[0], UserMessageEvent) assert isinstance(events[1], CompactStartEvent) assert isinstance(events[2], CompactEndEvent) assert isinstance(events[3], AssistantEvent) start: CompactStartEvent = events[1] end: CompactEndEvent = events[2] final: AssistantEvent = events[3] assert start.current_context_tokens == 2 assert start.threshold == 1 assert end.old_context_tokens == 2 assert end.new_context_tokens >= 1 assert final.content == "" roles = [r for r, _ in observed] assert roles == [Role.system, Role.user, Role.assistant] assert observed[1][1] is not None and "" in observed[1][1] assert observed[2][1] == "" auto_compact = [ e for e in telemetry_events if e.get("event_name") == "vibe/auto_compact_triggered" ] assert len(auto_compact) == 1