diff --git a/scripts/migrate_hermes.py b/scripts/migrate_hermes.py index 64a2d6e..0555e5a 100644 --- a/scripts/migrate_hermes.py +++ b/scripts/migrate_hermes.py @@ -41,6 +41,9 @@ import sys import time from datetime import datetime, timezone +# корень репо Simbiot (файл лежит в scripts/): импорт стора + OUT-пакет +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + MAX_HISTORY_SESSIONS = 40 # сколько последних сессий с диалогом переносим MAX_HISTORY_MSGS_PER_SESSION = 40 MAX_TOTAL_HISTORY_MSGS = 150 @@ -135,23 +138,47 @@ def extract_history(hermes_dir: str, out_dir: str) -> dict: return res db = sqlite3.connect(f"file:{state}?mode=ro", uri=True) db.row_factory = sqlite3.Row - sessions = db.execute(""" + # схемы Гермеса различаются по версиям (t-261001124130: у Риты нет + # last_activity_at) — толерантный ORDER BY + scols = {r[1] for r in db.execute("PRAGMA table_info(sessions)")} + if "last_activity_at" in scols: + order_expr = "COALESCE(s.last_activity_at, s.started_at)" + last_expr = "s.last_activity_at" + else: + order_expr = "s.started_at" + last_expr = "s.started_at" + # два прохода (t-261001124130): сначала ЖИВЫЕ чаты (telegram/matrix/cli/ + # subagent) — крон-сессии (watchdog-пинги, отчёты) шумом съедали весь кап; + # крон берём только в остаток лимита + sessions = db.execute(f""" SELECT s.id, s.source, s.chat_type, s.display_name, s.title, - s.started_at, s.last_activity_at, COUNT(m.id) n + s.started_at, {last_expr} AS last_at, COUNT(m.id) n FROM sessions s JOIN messages m ON m.session_id = s.id WHERE m.active = 1 AND m.role IN ('user', 'assistant') + AND COALESCE(s.source, 'cron') != 'cron' GROUP BY s.id HAVING n >= 2 - ORDER BY COALESCE(s.last_activity_at, s.started_at) DESC + ORDER BY {order_expr} DESC LIMIT ?""", (MAX_HISTORY_SESSIONS,)).fetchall() - res["sessions_total"] = len(sessions) + cron_sessions = db.execute(f""" + SELECT s.id, s.source, s.chat_type, s.display_name, s.title, + s.started_at, {last_expr} AS last_at, COUNT(m.id) n + FROM sessions s JOIN messages m ON m.session_id = s.id + WHERE m.active = 1 AND m.role IN ('user', 'assistant') + AND COALESCE(s.source, 'cron') = 'cron' + GROUP BY s.id + HAVING n >= 2 + ORDER BY {order_expr} DESC + LIMIT ?""", (MAX_HISTORY_SESSIONS,)).fetchall() + all_sessions = list(sessions) + list(cron_sessions) # живые первыми + res["sessions_total"] = len(all_sessions) hdir = os.path.join(out_dir, "history") os.makedirs(hdir, exist_ok=True) idx_lines = ["# История диалогов Гермеса → Simbiot", "", "сессии с реальным диалогом (active=1, ≥2 сообщения),", f"капы: {MAX_HISTORY_MSGS_PER_SESSION}/сессия, {MAX_TOTAL_HISTORY_MSGS} всего", ""] total = 0 - for s in sessions: + for s in all_sessions: if total >= MAX_TOTAL_HISTORY_MSGS: idx_lines.append(f"- (усечено: достигнут глобальный кап {MAX_TOTAL_HISTORY_MSGS} сообщений)") break @@ -183,7 +210,7 @@ def extract_history(hermes_dir: str, out_dir: str) -> dict: total += len(msgs) idx_lines.append(f"- [{title}]({os.path.basename(path)}) — " f"{s['source'] or '?'}, {len(msgs)} сообщ., " - f"последнее {datetime.fromtimestamp(s['last_activity_at'] or s['started_at'] or 0, tz=timezone.utc).strftime('%Y-%m-%d')}") + f"последнее {datetime.fromtimestamp(s['last_at'] or s['started_at'] or 0, tz=timezone.utc).strftime('%Y-%m-%d')}") db.close() with open(os.path.join(out_dir, "history-index.md"), "w", encoding="utf-8") as f: f.write("\n".join(idx_lines) + "\n") @@ -341,7 +368,7 @@ def main(): ap.add_argument("--rag-script", default="/root/rag/rag.py") args = ap.parse_args() - simbiot_repo = os.path.dirname(os.path.abspath(__file__)) + simbiot_repo = REPO_ROOT out_dir = args.out or os.path.join(simbiot_repo, "hermes-migration") if args.apply: os.makedirs(out_dir, exist_ok=True)