Show local conversation activity in web console
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sqlite3
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
from threading import Lock
|
||||
@@ -8,17 +9,35 @@ from typing import Any
|
||||
|
||||
|
||||
class ConversationLogStore:
|
||||
"""Append-only local audit log for chat and tool activity."""
|
||||
"""SQLite-backed local audit log for chat and tool activity."""
|
||||
|
||||
def __init__(self, path: str | Path) -> None:
|
||||
self.path = Path(path)
|
||||
self._lock = Lock()
|
||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with self._connect() as connection:
|
||||
connection.execute("CREATE TABLE IF NOT EXISTS conversation_events (id INTEGER PRIMARY KEY AUTOINCREMENT, occurred_at TEXT NOT NULL, event_type TEXT NOT NULL, payload_json TEXT NOT NULL)")
|
||||
|
||||
def append(self, event: dict[str, Any]) -> None:
|
||||
record = {"timestamp": datetime.now(UTC).isoformat(), **_safe(event)}
|
||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with self._lock, self.path.open("a", encoding="utf-8") as stream:
|
||||
stream.write(json.dumps(record, ensure_ascii=True, default=str) + "\n")
|
||||
with self._lock, self._connect() as connection:
|
||||
connection.execute("INSERT INTO conversation_events (occurred_at, event_type, payload_json) VALUES (?, ?, ?)", (datetime.now(UTC).isoformat(), str(event.get("type") or "event"), json.dumps(_safe(event), ensure_ascii=True, default=str)))
|
||||
|
||||
def list_recent(self, *, limit: int = 200) -> list[dict[str, Any]]:
|
||||
with self._connect() as connection:
|
||||
rows = connection.execute("SELECT id, occurred_at, event_type, payload_json FROM conversation_events ORDER BY id DESC LIMIT ?", (max(1, min(limit, 1000)),)).fetchall()
|
||||
result = []
|
||||
for row in rows:
|
||||
try:
|
||||
payload = json.loads(row["payload_json"])
|
||||
except (TypeError, ValueError):
|
||||
payload = {}
|
||||
result.append({"id": row["id"], "occurred_at": row["occurred_at"], "event_type": row["event_type"], **payload})
|
||||
return result
|
||||
|
||||
def _connect(self) -> sqlite3.Connection:
|
||||
connection = sqlite3.connect(self.path)
|
||||
connection.row_factory = sqlite3.Row
|
||||
return connection
|
||||
|
||||
|
||||
def _safe(value: Any) -> Any:
|
||||
|
||||
Reference in New Issue
Block a user