vibe/vibe/core/session/saved_sessions.py
Mathias Gesbert 3f8487f761
v2.14.0 (#743)
Co-authored-by: Alexis Tacnet <alexis@mistral.ai>
Co-authored-by: Clément Drouin <clement.drouin@mistral.ai>
Co-authored-by: Guillaume LE GOFF <guillaume.lgf@gmail.com>
Co-authored-by: Lucas Marandat <31749711+lucasmrdt@users.noreply.github.com>
Co-authored-by: Maxime Dolores <maxime.dolores@ext.mistral.ai>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Quentin <quentin.torroba@mistral.ai>
Co-authored-by: Val <102326092+vdeva@users.noreply.github.com>
Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com>
Co-authored-by: p.vezia <166131032+le-codeur-rapide@users.noreply.github.com>
Co-authored-by: Hiba Chaabnia <Hiba-Chaabnia@users.noreply.github.com>
Co-authored-by: Nikhil Bhima <nikhilbhima@users.noreply.github.com>
Co-authored-by: Nkipohcs <Nkipohcs@users.noreply.github.com>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
2026-06-04 18:26:35 +02:00

87 lines
2.7 KiB
Python

from __future__ import annotations
import asyncio
import json
from pathlib import Path
import shutil
from typing import Any
from vibe.core.config import SessionLoggingConfig
from vibe.core.session import last_session_pointer
from vibe.core.session.session_loader import METADATA_FILENAME, SessionLoader
from vibe.core.session.session_logger import SessionLogger
from vibe.core.utils.io import read_safe
def _normalize_session_title(title: str) -> str:
normalized_title = title.strip()
if not normalized_title:
raise ValueError("Session title cannot be empty.")
return normalized_title
def _resolve_saved_session_dir(
session_id: str, session_config: SessionLoggingConfig
) -> Path:
session_dir = _find_saved_session_dir(session_id, session_config)
if session_dir is None:
raise ValueError(f"Session not found: {session_id}")
return session_dir
def _find_saved_session_dir(
session_id: str, session_config: SessionLoggingConfig
) -> Path | None:
for session_dir in SessionLoader._find_session_dirs_by_short_id(
session_id, session_config
):
try:
metadata = _load_raw_metadata(session_dir)
except (OSError, ValueError, json.JSONDecodeError):
continue
if metadata.get("session_id") == session_id:
return session_dir
return None
def _load_raw_metadata(session_dir: Path) -> dict[str, Any]:
metadata_path = session_dir / METADATA_FILENAME
metadata = json.loads(read_safe(metadata_path).text)
if not isinstance(metadata, dict):
raise ValueError(f"Session metadata must be an object: {metadata_path}")
return metadata
async def update_saved_session_title_at_path(
session_dir: Path, title: str
) -> dict[str, Any]:
normalized_title = _normalize_session_title(title)
metadata = _load_raw_metadata(session_dir)
updated_metadata = {**metadata, "title": normalized_title, "title_source": "manual"}
await SessionLogger.persist_metadata(updated_metadata, session_dir)
return updated_metadata
async def update_saved_session_title(
session_id: str, title: str, session_config: SessionLoggingConfig
) -> dict[str, Any]:
session_dir = _resolve_saved_session_dir(session_id, session_config)
return await update_saved_session_title_at_path(session_dir, title)
async def delete_saved_session(
session_id: str, session_config: SessionLoggingConfig
) -> None:
session_dir = _find_saved_session_dir(session_id, session_config)
if session_dir is None:
last_session_pointer.clear_matching(session_config, session_id)
return
await asyncio.to_thread(shutil.rmtree, session_dir)
last_session_pointer.clear_matching(session_config, session_id)