Newer
Older
navi-1 / tests / unit / workers / test_compression_worker.py
"""Tests for the post-turn CompressionWorker."""

from __future__ import annotations

import pytest

from navi.core.events import ContextCompressed
from navi.core.session import InMemorySessionStore, Session
from navi.workers.base import WorkerContext
from navi.workers.compressor import CompressionWorker
from navi.llm.base import Message
from tests.conftest_factory import FakeLLMBackend


def _ctx(session_id: str, llm, store) -> WorkerContext:
    return WorkerContext(
        session_id=session_id,
        context_tokens=50_000,  # over the 0.70 threshold -> worker attempts compression
        max_context_tokens=65536,
        llm=llm,
        model="test",
        temperature=0.3,
        session_store=store,
    )


@pytest.mark.asyncio
async def test_worker_compresses_single_long_turn():
    """Regression: a single long autonomous turn (one user message + many tool
    iterations = one turn) used to no-op because the worker called
    compress_context without keep_recent_messages. Now it mirrors the midturn
    path and compresses via the intra-turn fallback."""
    worker = CompressionWorker()
    backend = FakeLLMBackend(responses=["summary of the work so far"])
    store = InMemorySessionStore()
    session = Session(profile_id="test")
    store._sessions[session.id] = session
    session.context.append(Message(role="user", content="do the task"))
    for i in range(20):
        session.context.append(Message(role="assistant", content=f"step {i} " * 40))

    result = await worker.run(session, _ctx(session.id, backend, store))
    assert any(isinstance(ev, ContextCompressed) for ev in result.events)
    compressed = next(ev for ev in result.events if isinstance(ev, ContextCompressed))
    assert compressed.messages_after < compressed.messages_before
    assert compressed.summary == "summary of the work so far"


@pytest.mark.asyncio
async def test_worker_no_op_when_context_small():
    """Below the token threshold the worker does nothing."""
    worker = CompressionWorker()
    backend = FakeLLMBackend(responses=["irrelevant"])
    store = InMemorySessionStore()
    session = Session(profile_id="test")
    store._sessions[session.id] = session
    session.context.append(Message(role="user", content="hi"))
    session.context.append(Message(role="assistant", content="hello"))

    ctx = WorkerContext(
        session_id=session.id,
        context_tokens=10,  # well below threshold
        max_context_tokens=65536,
        llm=backend,
        model="test",
        temperature=0.3,
        session_store=store,
    )
    result = await worker.run(session, ctx)
    assert result.events == []


def test_worker_keep_recent_messages_mirrors_midturn():
    """The worker passes keep_recent_messages=max(12, context_keep_recent*2),
    matching the midturn auto-compress path (source of truth for the intra-turn
    fallback). Guards against regressing back to keep_recent_messages=None."""
    import inspect

    src = inspect.getsource(CompressionWorker.run)
    assert "keep_recent_messages" in src
    assert "max(12" in src