Co-authored-by: Clément Drouin <clement.drouin@mistral.ai>
Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com>
Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai>
Co-authored-by: allansimon-mistral <allan.simon@ext.mistral.ai>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Clément Sirieix 2026-05-07 13:55:56 +02:00 committed by GitHub
parent 4972dd5694
commit b23f49e5f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 2342 additions and 240 deletions

View file

@ -5,33 +5,41 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from vibe.core.session.resume_sessions import (
SHORT_SESSION_ID_LEN,
list_remote_resume_sessions,
short_session_id,
)
from vibe.core.session.session_id import shorten_session_id
class TestShortenSessionId:
def test_shortens_to_first_8_chars(self) -> None:
sid = "abcdef1234567890"
assert shorten_session_id(sid) == "abcdef12"
def test_from_end_shortens_to_last_8_chars(self) -> None:
sid = "abcdef1234567890"
assert shorten_session_id(sid, from_end=True) == "34567890"
def test_returns_full_id_when_shorter_than_limit(self) -> None:
sid = "abc"
assert shorten_session_id(sid) == "abc"
assert shorten_session_id(sid, from_end=True) == "abc"
class TestShortSessionId:
def test_local_shortens_to_first_chars(self) -> None:
def test_local_delegates_to_shorten(self) -> None:
sid = "abcdef1234567890"
result = short_session_id(sid)
assert result == sid[:SHORT_SESSION_ID_LEN]
assert len(result) == SHORT_SESSION_ID_LEN
assert short_session_id(sid) == shorten_session_id(sid)
def test_local_is_default(self) -> None:
sid = "abcdef1234567890"
assert short_session_id(sid) == short_session_id(sid, source="local")
def test_remote_shortens_to_last_chars(self) -> None:
def test_remote_delegates_to_shorten_from_end(self) -> None:
sid = "abcdef1234567890"
result = short_session_id(sid, source="remote")
assert result == sid[-SHORT_SESSION_ID_LEN:]
assert len(result) == SHORT_SESSION_ID_LEN
def test_returns_full_id_when_shorter_than_limit(self) -> None:
sid = "abc"
assert short_session_id(sid) == "abc"
assert short_session_id(sid, source="remote") == "abc"
assert short_session_id(sid, source="remote") == shorten_session_id(
sid, from_end=True
)
def test_empty_string(self) -> None:
assert short_session_id("") == ""

View file

@ -11,6 +11,7 @@ import pytest
from tests.conftest import build_test_vibe_config
from vibe.core.agents.models import AgentProfile, AgentSafety
from vibe.core.config import SessionLoggingConfig, VibeConfig
from vibe.core.loop import ScheduledLoop
from vibe.core.session.session_logger import SessionLogger
from vibe.core.tools.manager import ToolManager
from vibe.core.types import AgentStats, LLMMessage, Role, SessionMetadata
@ -868,3 +869,136 @@ class TestSessionLoggerCleanupTmpFiles:
logger.maybe_cleanup_tmp_files()
assert cleanup_spy.call_count == 2
class TestPersistLoops:
@pytest.mark.asyncio
async def test_writes_into_existing_metadata(
self,
session_config: SessionLoggingConfig,
mock_vibe_config: VibeConfig,
mock_tool_manager: ToolManager,
mock_agent_profile: AgentProfile,
) -> None:
logger = SessionLogger(session_config, "test-session-loops")
await logger.save_interaction(
messages=[
LLMMessage(role=Role.system, content="System prompt"),
LLMMessage(role=Role.user, content="Hello"),
LLMMessage(role=Role.assistant, content="Hi there!"),
],
stats=AgentStats(steps=1),
base_config=mock_vibe_config,
tool_manager=mock_tool_manager,
agent_profile=mock_agent_profile,
)
assert logger.session_metadata is not None
logger.session_metadata.loops = [
ScheduledLoop(
id="aabbccdd",
interval_seconds=30,
prompt="ping",
next_fire_at=12345.0,
created_at=12000.0,
)
]
await logger.persist_loops()
assert logger.session_dir is not None
with open(logger.session_dir / "meta.json") as f:
metadata = json.load(f)
assert metadata["session_id"] == "test-session-loops"
assert metadata["total_messages"] == 2
assert metadata["loops"] == [
{
"id": "aabbccdd",
"interval_seconds": 30,
"prompt": "ping",
"next_fire_at": 12345.0,
"created_at": 12000.0,
}
]
@pytest.mark.asyncio
async def test_noop_when_metadata_file_missing(
self, session_config: SessionLoggingConfig
) -> None:
logger = SessionLogger(session_config, "no-meta-session")
assert logger.session_dir is not None
# No save_interaction was called -> meta.json does not exist
assert not (logger.session_dir / "meta.json").exists()
assert logger.session_metadata is not None
logger.session_metadata.loops = [
ScheduledLoop(
id="aabbccdd",
interval_seconds=30,
prompt="ping",
next_fire_at=1.0,
created_at=0.0,
)
]
await logger.persist_loops()
assert not (logger.session_dir / "meta.json").exists()
@pytest.mark.asyncio
async def test_noop_when_logging_disabled(
self, disabled_session_config: SessionLoggingConfig
) -> None:
logger = SessionLogger(disabled_session_config, "ignored")
# Should not raise even though session_metadata is None
await logger.persist_loops()
@pytest.mark.asyncio
async def test_subsequent_save_interaction_preserves_loops(
self,
session_config: SessionLoggingConfig,
mock_vibe_config: VibeConfig,
mock_tool_manager: ToolManager,
mock_agent_profile: AgentProfile,
) -> None:
logger = SessionLogger(session_config, "loops-vs-save")
messages = [
LLMMessage(role=Role.system, content="System prompt"),
LLMMessage(role=Role.user, content="Hello"),
LLMMessage(role=Role.assistant, content="Hi there!"),
]
await logger.save_interaction(
messages=messages,
stats=AgentStats(steps=1),
base_config=mock_vibe_config,
tool_manager=mock_tool_manager,
agent_profile=mock_agent_profile,
)
assert logger.session_metadata is not None
logger.session_metadata.loops = [
ScheduledLoop(
id="aabbccdd",
interval_seconds=30,
prompt="ping",
next_fire_at=12345.0,
created_at=12000.0,
)
]
await logger.persist_loops()
# A subsequent save (e.g. user sends another message) must not
# overwrite the on-disk loops with the stale in-memory value.
more_messages = [*messages, LLMMessage(role=Role.user, content="Again")]
await logger.save_interaction(
messages=more_messages,
stats=AgentStats(steps=2),
base_config=mock_vibe_config,
tool_manager=mock_tool_manager,
agent_profile=mock_agent_profile,
)
assert logger.session_dir is not None
with open(logger.session_dir / "meta.json") as f:
metadata = json.load(f)
assert len(metadata["loops"]) == 1
assert metadata["loops"][0]["id"] == "aabbccdd"