File size: 2,351 Bytes
6cd1906
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""セッションごとのデータ保存先を管理する。

複数のユーザーが同じ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