mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-06-02 06:13:46 +02:00
Phase 4-6: Dead code removal, performance, minor fixes
Phase 4: - Remove legacy SessionRecord, _sessions, _msg_to_session from SessionStore - Fix hardcoded provider in root endpoint (use settings.provider_type) - Update session store tests Phase 5: - Use list-based string accumulation in ThinkingSegment, TextSegment, ToolCallSegment - Cache MAX_MESSAGE_LOG_ENTRIES_PER_CHAT at SessionStore init - Use iterative DFS in MessageTree.get_descendants Phase 6: - Add comment for abstract async generator workaround in BaseProvider - Rename TELEGRAM_EDIT log tags to PLATFORM_EDIT in handler Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>
This commit is contained in:
+17
-64
@@ -9,24 +9,10 @@ import json
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional, Dict, List, Any
|
||||
from dataclasses import dataclass, asdict
|
||||
import threading
|
||||
from loguru import logger
|
||||
|
||||
|
||||
@dataclass
|
||||
class SessionRecord:
|
||||
"""A single session record."""
|
||||
|
||||
session_id: str
|
||||
chat_id: str
|
||||
initial_msg_id: str
|
||||
last_msg_id: str
|
||||
platform: str
|
||||
created_at: str
|
||||
updated_at: str
|
||||
|
||||
|
||||
class SessionStore:
|
||||
"""
|
||||
Persistent storage for message ↔ Claude session mappings and message trees.
|
||||
@@ -38,10 +24,6 @@ class SessionStore:
|
||||
def __init__(self, storage_path: str = "sessions.json"):
|
||||
self.storage_path = storage_path
|
||||
self._lock = threading.Lock()
|
||||
self._sessions: Dict[str, SessionRecord] = {}
|
||||
self._msg_to_session: Dict[
|
||||
str, str
|
||||
] = {} # "platform:chat_id:msg_id" -> session_id
|
||||
self._trees: Dict[str, dict] = {} # root_id -> tree data
|
||||
self._node_to_tree: Dict[str, str] = {} # node_id -> root_id
|
||||
# Per-chat message ID log used to support best-effort UI clearing (/clear).
|
||||
@@ -51,12 +33,15 @@ class SessionStore:
|
||||
self._dirty = False
|
||||
self._save_timer: Optional[threading.Timer] = None
|
||||
self._save_debounce_secs = 0.5
|
||||
cap_raw = os.getenv("MAX_MESSAGE_LOG_ENTRIES_PER_CHAT", "").strip()
|
||||
try:
|
||||
self._message_log_cap: Optional[int] = (
|
||||
int(cap_raw) if cap_raw else None
|
||||
)
|
||||
except ValueError:
|
||||
self._message_log_cap = None
|
||||
self._load()
|
||||
|
||||
def _make_key(self, platform: str, chat_id: str, msg_id: str) -> str:
|
||||
"""Create a unique key from platform, chat_id and msg_id."""
|
||||
return f"{platform}:{chat_id}:{msg_id}"
|
||||
|
||||
def _make_chat_key(self, platform: str, chat_id: str) -> str:
|
||||
return f"{platform}:{chat_id}"
|
||||
|
||||
@@ -69,25 +54,6 @@ class SessionStore:
|
||||
with open(self.storage_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Load sessions (legacy support)
|
||||
for sid, record_data in data.get("sessions", {}).items():
|
||||
if "platform" not in record_data:
|
||||
record_data["platform"] = "telegram"
|
||||
for field in ["chat_id", "initial_msg_id", "last_msg_id"]:
|
||||
if isinstance(record_data.get(field), int):
|
||||
record_data[field] = str(record_data[field])
|
||||
|
||||
record = SessionRecord(**record_data)
|
||||
self._sessions[sid] = record
|
||||
self._msg_to_session[
|
||||
self._make_key(
|
||||
record.platform, record.chat_id, record.initial_msg_id
|
||||
)
|
||||
] = sid
|
||||
self._msg_to_session[
|
||||
self._make_key(record.platform, record.chat_id, record.last_msg_id)
|
||||
] = sid
|
||||
|
||||
# Load trees
|
||||
self._trees = data.get("trees", {})
|
||||
self._node_to_tree = data.get("node_to_tree", {})
|
||||
@@ -124,8 +90,8 @@ class SessionStore:
|
||||
self._message_log_ids[chat_key] = seen
|
||||
|
||||
logger.info(
|
||||
f"Loaded {len(self._sessions)} sessions, {len(self._trees)} trees, "
|
||||
f"and {sum(len(v) for v in self._message_log.values())} msg_ids from {self.storage_path}"
|
||||
f"Loaded {len(self._trees)} trees and "
|
||||
f"{sum(len(v) for v in self._message_log.values())} msg_ids from {self.storage_path}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to load sessions: {e}")
|
||||
@@ -134,9 +100,6 @@ class SessionStore:
|
||||
"""Persist sessions and trees to disk. Caller must hold self._lock."""
|
||||
try:
|
||||
data = {
|
||||
"sessions": {
|
||||
sid: asdict(record) for sid, record in self._sessions.items()
|
||||
},
|
||||
"trees": self._trees,
|
||||
"node_to_tree": self._node_to_tree,
|
||||
"message_log": self._message_log,
|
||||
@@ -211,22 +174,14 @@ class SessionStore:
|
||||
seen.add(mid)
|
||||
|
||||
# Optional cap to prevent unbounded growth if configured.
|
||||
# Default is unlimited as requested.
|
||||
try:
|
||||
cap_raw = os.getenv("MAX_MESSAGE_LOG_ENTRIES_PER_CHAT", "").strip()
|
||||
if cap_raw:
|
||||
cap = int(cap_raw)
|
||||
if cap > 0:
|
||||
items = self._message_log.get(chat_key, [])
|
||||
if len(items) > cap:
|
||||
# Drop oldest entries and rebuild seen set.
|
||||
self._message_log[chat_key] = items[-cap:]
|
||||
self._message_log_ids[chat_key] = {
|
||||
str(x.get("message_id"))
|
||||
for x in self._message_log[chat_key]
|
||||
}
|
||||
except Exception:
|
||||
pass
|
||||
if self._message_log_cap is not None and self._message_log_cap > 0:
|
||||
items = self._message_log.get(chat_key, [])
|
||||
if len(items) > self._message_log_cap:
|
||||
self._message_log[chat_key] = items[-self._message_log_cap :]
|
||||
self._message_log_ids[chat_key] = {
|
||||
str(x.get("message_id"))
|
||||
for x in self._message_log[chat_key]
|
||||
}
|
||||
|
||||
self._schedule_save()
|
||||
|
||||
@@ -244,8 +199,6 @@ class SessionStore:
|
||||
def clear_all(self) -> None:
|
||||
"""Clear all stored sessions/trees/mappings and persist an empty store."""
|
||||
with self._lock:
|
||||
self._sessions.clear()
|
||||
self._msg_to_session.clear()
|
||||
self._trees.clear()
|
||||
self._node_to_tree.clear()
|
||||
self._message_log.clear()
|
||||
|
||||
Reference in New Issue
Block a user