generated from coulomb/repo-seed
graph store memory
This commit is contained in:
@@ -6,6 +6,7 @@ from dataclasses import dataclass, field
|
|||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from kontextual_engine.core import (
|
from kontextual_engine.core import (
|
||||||
|
AuditEvent,
|
||||||
LifecycleState,
|
LifecycleState,
|
||||||
MemoryEdgeRecord,
|
MemoryEdgeRecord,
|
||||||
MemoryEventRecord,
|
MemoryEventRecord,
|
||||||
@@ -21,6 +22,7 @@ class InMemoryMemoryGraphRepository:
|
|||||||
nodes: dict[str, MemoryNodeRecord] = field(default_factory=dict)
|
nodes: dict[str, MemoryNodeRecord] = field(default_factory=dict)
|
||||||
edges: dict[str, MemoryEdgeRecord] = field(default_factory=dict)
|
edges: dict[str, MemoryEdgeRecord] = field(default_factory=dict)
|
||||||
events: dict[str, MemoryEventRecord] = field(default_factory=dict)
|
events: dict[str, MemoryEventRecord] = field(default_factory=dict)
|
||||||
|
audit_events: dict[str, AuditEvent] = field(default_factory=dict)
|
||||||
|
|
||||||
def save_memory_profile(self, profile: MemoryProfileRecord) -> MemoryProfileRecord:
|
def save_memory_profile(self, profile: MemoryProfileRecord) -> MemoryProfileRecord:
|
||||||
self.profiles[str(profile.profile_id)] = profile
|
self.profiles[str(profile.profile_id)] = profile
|
||||||
@@ -124,3 +126,38 @@ class InMemoryMemoryGraphRepository:
|
|||||||
if kind is not None:
|
if kind is not None:
|
||||||
events = [event for event in events if event.kind == kind]
|
events = [event for event in events if event.kind == kind]
|
||||||
return sorted(events, key=lambda event: (event.graph_id, event.timestamp, event.contract_event_id))
|
return sorted(events, key=lambda event: (event.graph_id, event.timestamp, event.contract_event_id))
|
||||||
|
|
||||||
|
def save_memory_audit_event(self, event: AuditEvent) -> AuditEvent:
|
||||||
|
self.audit_events[str(event.event_id)] = event
|
||||||
|
return event
|
||||||
|
|
||||||
|
def get_memory_audit_event(self, event_id: str) -> AuditEvent:
|
||||||
|
try:
|
||||||
|
return self.audit_events[event_id]
|
||||||
|
except KeyError as exc:
|
||||||
|
raise NotFoundError("Memory audit event not found", details={"event_id": event_id}) from exc
|
||||||
|
|
||||||
|
def list_memory_audit_events(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
graph_id: str | None = None,
|
||||||
|
correlation_id: str | None = None,
|
||||||
|
operation: str | None = None,
|
||||||
|
) -> list[AuditEvent]:
|
||||||
|
events: Iterable[AuditEvent] = self.audit_events.values()
|
||||||
|
if graph_id is not None:
|
||||||
|
events = [event for event in events if _audit_event_matches_graph(event, graph_id)]
|
||||||
|
if correlation_id is not None:
|
||||||
|
events = [event for event in events if event.correlation_id == correlation_id]
|
||||||
|
if operation is not None:
|
||||||
|
events = [event for event in events if event.operation == operation]
|
||||||
|
return sorted(events, key=lambda event: (event.occurred_at, event.event_id))
|
||||||
|
|
||||||
|
|
||||||
|
def _audit_event_matches_graph(event: AuditEvent, graph_id: str) -> bool:
|
||||||
|
if event.target == f"memory-graph:{graph_id}":
|
||||||
|
return True
|
||||||
|
if event.details.get("graph_id") == graph_id:
|
||||||
|
return True
|
||||||
|
request = event.details.get("request")
|
||||||
|
return isinstance(request, dict) and request.get("graph_id") == graph_id
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
|
|
||||||
from kontextual_engine.core import (
|
from kontextual_engine.core import (
|
||||||
|
AuditEvent,
|
||||||
LifecycleState,
|
LifecycleState,
|
||||||
MemoryEdgeRecord,
|
MemoryEdgeRecord,
|
||||||
MemoryEventRecord,
|
MemoryEventRecord,
|
||||||
@@ -45,3 +46,13 @@ class MemoryGraphRepository(Protocol):
|
|||||||
graph_id: str | None = None,
|
graph_id: str | None = None,
|
||||||
kind: str | None = None,
|
kind: str | None = None,
|
||||||
) -> list[MemoryEventRecord]: ...
|
) -> list[MemoryEventRecord]: ...
|
||||||
|
|
||||||
|
def save_memory_audit_event(self, event: AuditEvent) -> AuditEvent: ...
|
||||||
|
def get_memory_audit_event(self, event_id: str) -> AuditEvent: ...
|
||||||
|
def list_memory_audit_events(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
graph_id: str | None = None,
|
||||||
|
correlation_id: str | None = None,
|
||||||
|
operation: str | None = None,
|
||||||
|
) -> list[AuditEvent]: ...
|
||||||
|
|||||||
@@ -448,6 +448,59 @@ class MemoryPackageExportResult:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MemoryRuntimeExportRequest:
|
||||||
|
graph_id: str
|
||||||
|
include_nodes: bool = True
|
||||||
|
include_edges: bool = True
|
||||||
|
include_events: bool = True
|
||||||
|
include_audit_events: bool = True
|
||||||
|
include_retired: bool = True
|
||||||
|
event_kinds: tuple[str, ...] = ()
|
||||||
|
operations: tuple[str, ...] = ()
|
||||||
|
correlation_id: str | None = None
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
object.__setattr__(self, "event_kinds", tuple(self.event_kinds))
|
||||||
|
object.__setattr__(self, "operations", tuple(self.operations))
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"graph_id": self.graph_id,
|
||||||
|
"include_nodes": self.include_nodes,
|
||||||
|
"include_edges": self.include_edges,
|
||||||
|
"include_events": self.include_events,
|
||||||
|
"include_audit_events": self.include_audit_events,
|
||||||
|
"include_retired": self.include_retired,
|
||||||
|
"event_kinds": list(self.event_kinds),
|
||||||
|
"operations": list(self.operations),
|
||||||
|
"correlation_id": self.correlation_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MemoryRuntimeExportResult:
|
||||||
|
request: MemoryRuntimeExportRequest
|
||||||
|
correlation_id: str
|
||||||
|
envelope: dict[str, Any] = field(default_factory=dict)
|
||||||
|
audit_event: AuditEvent | None = None
|
||||||
|
diagnostics: tuple[Diagnostic, ...] = ()
|
||||||
|
success: bool = True
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
object.__setattr__(self, "diagnostics", tuple(self.diagnostics))
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"request": self.request.to_dict(),
|
||||||
|
"correlation_id": self.correlation_id,
|
||||||
|
"success": self.success,
|
||||||
|
"envelope": dict(self.envelope),
|
||||||
|
"audit_event": self.audit_event.to_dict() if self.audit_event else None,
|
||||||
|
"diagnostics": [diagnostic.to_dict() for diagnostic in self.diagnostics],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class MemoryRuntimeService:
|
class MemoryRuntimeService:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|||||||
Reference in New Issue
Block a user