Project-Rivet / v2 /engine /session.py
HumboldtJoker's picture
Upload folder using huggingface_hub
4554903 verified
Raw
History Blame Contribute Delete
2.97 kB
"""Per-user sessions with evidence tracking.
Confidence in Rivet is earned, not asserted. Every file a chip actually
reads during a plan is recorded here; the discipline gate grades the
final answer against this record:
HIGH the answer's claims are backed by source files read this session
MEDIUM backed by architecture map / audit / pack knowledge only
LOW reasoning from architecture with no matching source at all
Sessions are isolated per user (faculty-wide deployment requirement —
no context bleed between users).
"""
import time
from dataclasses import dataclass, field
@dataclass
class Session:
user_id: str
created_at: float = field(default_factory=time.time)
last_active: float = field(default_factory=time.time)
history: list = field(default_factory=list) # [{role, content}]
files_read: set = field(default_factory=set) # repo-relative paths
evidence: list = field(default_factory=list) # [{kind, ref, chip}]
request_count: int = 0
def touch(self) -> None:
self.last_active = time.time()
def record_file_read(self, path: str, chip: str) -> None:
self.files_read.add(path)
self.evidence.append({"kind": "source_file", "ref": path, "chip": chip})
def record_evidence(self, kind: str, ref: str, chip: str) -> None:
self.evidence.append({"kind": kind, "ref": ref, "chip": chip})
def add_turn(self, role: str, content: str, max_turns: int = 20) -> None:
self.history.append({"role": role, "content": content})
if len(self.history) > max_turns:
self.history = self.history[-max_turns:]
class SessionManager:
def __init__(self, ttl_seconds: int = 3600, rate_limit_per_hour: int = 60):
self.ttl = ttl_seconds
self.rate_limit = rate_limit_per_hour
self._sessions: dict[str, Session] = {}
self._request_log: dict[str, list] = {}
def get(self, user_id: str) -> Session:
self._expire()
session = self._sessions.get(user_id)
if session is None:
session = Session(user_id=user_id)
self._sessions[user_id] = session
session.touch()
return session
def check_rate_limit(self, user_id: str) -> bool:
"""True if the user is within their hourly budget."""
now = time.time()
log = [t for t in self._request_log.get(user_id, []) if now - t < 3600]
self._request_log[user_id] = log
if len(log) >= self.rate_limit:
return False
log.append(now)
return True
def _expire(self) -> None:
now = time.time()
stale = [uid for uid, s in self._sessions.items()
if now - s.last_active > self.ttl]
for uid in stale:
del self._sessions[uid]
def stats(self) -> dict:
return {
"active_sessions": len(self._sessions),
"users": sorted(self._sessions.keys()),
}