Newer
Older
navi-1 / tests / unit / core / test_name_generator.py
"""Unit tests for the session name generator."""

import pytest

from navi.core.name_generator import generate_session_name
from navi.llm.base import LLMBackend, Message


class _FakeBackend(LLMBackend):
    def __init__(self, reply: str):
        self.reply = reply
        self.last_prompt = None

    async def complete(self, messages, tools=None, model=None, **kwargs):
        self.last_prompt = messages[-1].content
        return type("R", (), {"content": self.reply})()

    async def stream_complete(self, messages, tools=None, model=None, **kwargs):
        yield {"type": "text", "text": self.reply}


@pytest.mark.asyncio
async def test_folds_assistant_replies_into_context():
    backend = _FakeBackend("Setup of TLS on the proxy")
    name = await generate_session_name(
        ["привет", "ну так продолжай"],
        backend,
        "test-model",
        assistant_messages=["Сделаю шаги: 1) сгенерирую ключи..." + ("x" * 1000)],
    )
    assert name == "Setup of TLS on the proxy"
    # The assistant reply is trimmed to its 600-char tail, not passed whole
    assert "xxxxx" not in backend.last_prompt.replace("x" * 600, "")
    tail_len = len("Assistant replies:\n") + 600
    assert len(backend.last_prompt) - len(backend.last_prompt.split("Assistant replies:\n")[0]) == tail_len


@pytest.mark.asyncio
async def test_no_topic_still_yields_none():
    backend = _FakeBackend("NO_TITLE")
    name = await generate_session_name(
        ["привет", "как дела?"],
        backend,
        "test-model",
        assistant_messages=["Тоже привет!"],
    )
    assert name is None


@pytest.mark.asyncio
async def test_without_assistant_replies_unchanged():
    backend = _FakeBackend("Debugging the deploy")
    name = await generate_session_name(["fix the deploy"], backend, "test-model")
    assert name == "Debugging the deploy"
    assert "Assistant replies:" not in backend.last_prompt