"""EntityStore — Entitäts-Verwaltung für Tier 2.""" import json import sqlite3 import time import uuid as uuid_mod from dataclasses import dataclass from typing import List, Optional @dataclass class Entity: uuid: str name: str aliases: List[str] entity_type: str description: Optional[str] first_seen: float last_seen: float occurrence_count: int metadata: dict class EntityStore: def __init__(self, conn: sqlite3.Connection): self.conn = conn def ensure( self, name: str, entity_type: str, aliases: Optional[List[str]] = None, description: Optional[str] = None, metadata: Optional[dict] = None, ) -> Entity: existing = self._find_by_name(name) if existing: # Aktualisiere last_seen und occurrence_count self.conn.execute( "UPDATE entities SET last_seen = ?, occurrence_count = occurrence_count + 1 WHERE uuid = ?", (time.time(), existing.uuid), ) self.conn.commit() return self.get_by_uuid(existing.uuid) ent_uuid = str(uuid_mod.uuid4()) now = time.time() self.conn.execute( """ INSERT INTO entities (uuid, name, aliases, entity_type, description, first_seen, last_seen, occurrence_count, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( ent_uuid, name, json.dumps(aliases or []), entity_type, description, now, now, 1, json.dumps(metadata or {}), ), ) self.conn.commit() return self.get_by_uuid(ent_uuid) def _find_by_name(self, name: str) -> Optional[Entity]: row = self.conn.execute( "SELECT * FROM entities WHERE name = ? COLLATE NOCASE LIMIT 1", (name,) ).fetchone() return self._row_to_entity(row) if row else None def get_by_uuid(self, ent_uuid: str) -> Optional[Entity]: row = self.conn.execute("SELECT * FROM entities WHERE uuid = ? LIMIT 1", (ent_uuid,)).fetchone() return self._row_to_entity(row) if row else None def query( self, name: Optional[str] = None, entity_type: Optional[str] = None, limit: int = 10, ) -> List[Entity]: sql = "SELECT * FROM entities WHERE 1=1" params: List = [] if name: sql += " AND (name LIKE ? OR aliases LIKE ?)" params.extend([f"%{name}%", f"%{name}%"]) if entity_type: sql += " AND entity_type = ?" params.append(entity_type) sql += " ORDER BY occurrence_count DESC, last_seen DESC LIMIT ?" params.append(limit) rows = self.conn.execute(sql, params).fetchall() return [self._row_to_entity(r) for r in rows] def _row_to_entity(self, row: sqlite3.Row) -> Entity: return Entity( uuid=row["uuid"], name=row["name"], aliases=json.loads(row["aliases"] or "[]"), entity_type=row["entity_type"], description=row["description"], first_seen=row["first_seen"], last_seen=row["last_seen"], occurrence_count=row["occurrence_count"], metadata=json.loads(row["metadata"] or "{}"), )