Co-authored-by: Quentin Torroba <quentin.torroba@mistral.ai> Co-authored-by: Clément Siriex <clement.sirieix@mistral.ai> Co-authored-by: Kim-Adeline Miguel <kimadeline.miguel@mistral.ai> Co-authored-by: Michel Thomazo <michel.thomazo@mistral.ai> Co-authored-by: Clément Drouin <clement.drouin@mistral.ai>
242 lines
7.9 KiB
Python
242 lines
7.9 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from tests.acp.conftest import _create_acp_agent
|
|
from vibe.core.config import MissingAPIKeyError, SessionLoggingConfig
|
|
|
|
|
|
class TestListSessions:
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_empty(self, temp_session_dir: Path) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
session_config = SessionLoggingConfig(
|
|
save_dir=str(temp_session_dir), session_prefix="session", enabled=True
|
|
)
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_config = mock_load.return_value
|
|
mock_config.session_logging = session_config
|
|
|
|
response = await acp_agent.list_sessions()
|
|
|
|
assert response.sessions == []
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_returns_all_sessions(
|
|
self, temp_session_dir: Path, create_test_session
|
|
) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"aaaaaaaa-1111",
|
|
"/home/user/project1",
|
|
title="First session",
|
|
end_time="2024-01-01T12:00:00Z",
|
|
)
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"bbbbbbbb-2222",
|
|
"/home/user/project2",
|
|
title="Second session",
|
|
end_time="2024-01-01T13:00:00Z",
|
|
)
|
|
|
|
session_config = SessionLoggingConfig(
|
|
save_dir=str(temp_session_dir), session_prefix="session", enabled=True
|
|
)
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_config = mock_load.return_value
|
|
mock_config.session_logging = session_config
|
|
|
|
response = await acp_agent.list_sessions()
|
|
|
|
assert len(response.sessions) == 2
|
|
session_ids = {s.session_id for s in response.sessions}
|
|
assert "aaaaaaaa-1111" in session_ids
|
|
assert "bbbbbbbb-2222" in session_ids
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_filters_by_cwd(
|
|
self, temp_session_dir: Path, create_test_session
|
|
) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"aaaaaaaa-proj1",
|
|
"/home/user/project1",
|
|
title="Project 1 session",
|
|
)
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"bbbbbbbb-proj2",
|
|
"/home/user/project2",
|
|
title="Project 2 session",
|
|
)
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"cccccccc-proj1",
|
|
"/home/user/project1",
|
|
title="Another Project 1 session",
|
|
)
|
|
|
|
session_config = SessionLoggingConfig(
|
|
save_dir=str(temp_session_dir), session_prefix="session", enabled=True
|
|
)
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_config = mock_load.return_value
|
|
mock_config.session_logging = session_config
|
|
|
|
response = await acp_agent.list_sessions(cwd="/home/user/project1")
|
|
|
|
assert len(response.sessions) == 2
|
|
for session in response.sessions:
|
|
assert session.cwd == "/home/user/project1"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_sorted_by_updated_at(
|
|
self, temp_session_dir: Path, create_test_session
|
|
) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"oldest-s",
|
|
"/home/user/project",
|
|
title="Oldest",
|
|
end_time="2024-01-01T10:00:00Z",
|
|
)
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"newest-s",
|
|
"/home/user/project",
|
|
title="Newest",
|
|
end_time="2024-01-01T14:00:00Z",
|
|
)
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"middle-s",
|
|
"/home/user/project",
|
|
title="Middle",
|
|
end_time="2024-01-01T12:00:00Z",
|
|
)
|
|
|
|
session_config = SessionLoggingConfig(
|
|
save_dir=str(temp_session_dir), session_prefix="session", enabled=True
|
|
)
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_config = mock_load.return_value
|
|
mock_config.session_logging = session_config
|
|
|
|
response = await acp_agent.list_sessions()
|
|
|
|
assert len(response.sessions) == 3
|
|
|
|
assert response.sessions[0].title == "Newest"
|
|
assert response.sessions[1].title == "Middle"
|
|
assert response.sessions[2].title == "Oldest"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_includes_session_info_fields(
|
|
self, temp_session_dir: Path, create_test_session
|
|
) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
create_test_session(
|
|
temp_session_dir,
|
|
"test-session-123",
|
|
"/home/user/project",
|
|
title="Test Session Title",
|
|
end_time="2024-01-15T10:30:00Z",
|
|
)
|
|
|
|
session_config = SessionLoggingConfig(
|
|
save_dir=str(temp_session_dir), session_prefix="session", enabled=True
|
|
)
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_config = mock_load.return_value
|
|
mock_config.session_logging = session_config
|
|
|
|
response = await acp_agent.list_sessions()
|
|
|
|
assert len(response.sessions) == 1
|
|
session = response.sessions[0]
|
|
assert session.session_id == "test-session-123"
|
|
assert session.cwd == "/home/user/project"
|
|
assert session.title == "Test Session Title"
|
|
# updated_at is normalized to UTC
|
|
assert session.updated_at is not None
|
|
assert session.updated_at.endswith("+00:00")
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_skips_invalid_sessions(
|
|
self, temp_session_dir: Path, create_test_session
|
|
) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
create_test_session(
|
|
temp_session_dir, "valid-se", "/home/user/project", title="Valid Session"
|
|
)
|
|
|
|
invalid_session = temp_session_dir / "session_20240101_120000_invalid1"
|
|
invalid_session.mkdir()
|
|
(invalid_session / "meta.json").write_text('{"session_id": "invalid"}')
|
|
|
|
no_id_session = temp_session_dir / "session_20240101_120001_noid0000"
|
|
no_id_session.mkdir()
|
|
(no_id_session / "messages.jsonl").write_text(
|
|
'{"role": "user", "content": "Hello"}\n'
|
|
)
|
|
(no_id_session / "meta.json").write_text(
|
|
'{"environment": {"working_directory": "/test"}}'
|
|
)
|
|
|
|
session_config = SessionLoggingConfig(
|
|
save_dir=str(temp_session_dir), session_prefix="session", enabled=True
|
|
)
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_config = mock_load.return_value
|
|
mock_config.session_logging = session_config
|
|
|
|
response = await acp_agent.list_sessions()
|
|
|
|
assert len(response.sessions) == 1
|
|
assert response.sessions[0].session_id == "valid-se"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_nonexistent_save_dir(self) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
session_config = SessionLoggingConfig(
|
|
save_dir="/nonexistent/path", session_prefix="session", enabled=True
|
|
)
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_config = mock_load.return_value
|
|
mock_config.session_logging = session_config
|
|
|
|
response = await acp_agent.list_sessions()
|
|
|
|
assert response.sessions == []
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_sessions_without_api_key(self) -> None:
|
|
acp_agent = _create_acp_agent()
|
|
|
|
with patch("vibe.acp.acp_agent_loop.VibeConfig.load") as mock_load:
|
|
mock_load.side_effect = MissingAPIKeyError("api_key", "mistral")
|
|
|
|
response = await acp_agent.list_sessions()
|
|
|
|
assert response.sessions == []
|