"""セッションごとのデータ保存先を管理する。 複数のユーザーが同じURLを開いても会話やメモリが混ざらないよう、 各ブラウザセッションに専用の data ディレクトリを割り当てる。 Streamlit は各セッションを別スレッドで実行するため、保存先は contextvar で持つ。app.py が各実行の冒頭で set_data_dir() を呼ぶ。 学習済みモデル(data/Models 以下)は全セッション共有の読み取り専用なので ここでは扱わない。 """ from __future__ import annotations import contextvars import shutil import time from pathlib import Path ROOT = Path(__file__).resolve().parent.parent DEFAULT_DATA_DIR = ROOT / "data" SESSIONS_DIR = DEFAULT_DATA_DIR / "sessions" _data_dir: contextvars.ContextVar[Path] = contextvars.ContextVar( "rc_data_dir", default=DEFAULT_DATA_DIR ) def set_data_dir(path: Path | str) -> Path: """このセッション(スレッド)のデータ保存先を設定する。""" p = Path(path) p.mkdir(parents=True, exist_ok=True) _data_dir.set(p) return p def use_session(session_id: str) -> Path: """session_id 専用のデータディレクトリを作成して有効化する。""" return set_data_dir(SESSIONS_DIR / session_id) def data_dir() -> Path: return _data_dir.get() # --- 個別ファイル/ディレクトリ ------------------------------------------- def conversation_path() -> Path: return data_dir() / "conversation_history.json" def summary_path() -> Path: return data_dir() / "history_summary.json" def user_memory_path() -> Path: return data_dir() / "user_memory.json" def persona_style_path() -> Path: return data_dir() / "persona_style.json" def text_save_dir() -> Path: return data_dir() / "text_save" def cleanup_old_sessions(max_age_hours: float = 24.0) -> None: """古いセッションディレクトリを削除してディスクの肥大化を防ぐ。""" if not SESSIONS_DIR.exists(): return cutoff = time.time() - max_age_hours * 3600 for child in SESSIONS_DIR.iterdir(): if not child.is_dir(): continue try: if child.stat().st_mtime < cutoff: shutil.rmtree(child, ignore_errors=True) except OSError: continue