Replace EverMemOS with EverOS backend
This commit is contained in:
@ -1,12 +1,13 @@
|
||||
"""Application services for the generic Memory Gateway v1 API."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
from .config import get_config
|
||||
from .evermemos_client import EverMemOSError, EverMemOSClient
|
||||
from .everos_client import EverOSError, EverOSClient
|
||||
from .namespace import can_access_memory, default_namespace_for_context, user_long_term_namespace, visible_namespaces
|
||||
from .openviking_client import get_openviking_client
|
||||
from .repositories import MetadataRepository, repository
|
||||
@ -29,13 +30,23 @@ from .schemas import (
|
||||
UserRecord,
|
||||
Visibility,
|
||||
)
|
||||
from .workers.evermemos_worker import EverMemOSWorker
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConsolidationResult:
|
||||
session_id: str
|
||||
episodes: int
|
||||
candidates: list[MemoryRecord] = field(default_factory=list)
|
||||
promoted: list[MemoryRecord] = field(default_factory=list)
|
||||
duplicates: list[dict] = field(default_factory=list)
|
||||
review_drafts: list[str] = field(default_factory=list)
|
||||
conflicts: list[dict] = field(default_factory=list)
|
||||
|
||||
|
||||
class MemoryGatewayService:
|
||||
def __init__(self, repo: MetadataRepository = repository, evermemos_client: EverMemOSClient | None = None) -> None:
|
||||
def __init__(self, repo: MetadataRepository = repository, everos_client: EverOSClient | None = None) -> None:
|
||||
self.repo = repo
|
||||
self.evermemos_client = evermemos_client
|
||||
self.everos_client = everos_client
|
||||
|
||||
def create_user(self, request: CreateUserRequest) -> UserRecord:
|
||||
user = UserRecord(
|
||||
@ -204,10 +215,10 @@ class MemoryGatewayService:
|
||||
session_id=session_id,
|
||||
)
|
||||
target_namespace = request.target_namespace or user_long_term_namespace(request.user_id)
|
||||
config = get_config().evermemos
|
||||
config = get_config().everos
|
||||
if config.enabled:
|
||||
try:
|
||||
external_result = (self.evermemos_client or EverMemOSClient()).consolidate_session(
|
||||
external_result = (self.everos_client or EverOSClient()).consolidate_session(
|
||||
session_id=session_id,
|
||||
ctx=ctx,
|
||||
episodes=episodes,
|
||||
@ -217,32 +228,29 @@ class MemoryGatewayService:
|
||||
)
|
||||
result = self._persist_external_consolidation(external_result, ctx, session_id)
|
||||
backend = "external"
|
||||
except EverMemOSError as exc:
|
||||
except EverOSError as exc:
|
||||
error = str(exc)
|
||||
if not config.fallback_to_local:
|
||||
self._audit(
|
||||
"evermemos_commit_failed",
|
||||
"session",
|
||||
session_id,
|
||||
actor_user_id=request.user_id,
|
||||
actor_agent_id=request.agent_id,
|
||||
decision="deny",
|
||||
metadata={"error": error},
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"EverMemOS failed: {error}") from exc
|
||||
result = self._commit_session_locally(session_id, ctx, request)
|
||||
backend = "local-fallback"
|
||||
self._audit(
|
||||
"everos_commit_failed",
|
||||
"session",
|
||||
session_id,
|
||||
actor_user_id=request.user_id,
|
||||
actor_agent_id=request.agent_id,
|
||||
decision="deny",
|
||||
metadata={"error": error},
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"EverOS failed: {error}") from exc
|
||||
else:
|
||||
result = self._commit_session_locally(session_id, ctx, request)
|
||||
backend = "local-disabled"
|
||||
result = None
|
||||
backend = "disabled"
|
||||
else:
|
||||
result = None
|
||||
self._audit("commit_session", "session", session_id, actor_user_id=request.user_id, actor_agent_id=request.agent_id)
|
||||
if not result:
|
||||
return {"session_id": session_id, "episodes": len(episodes), "promoted": [], "evermemos_backend": backend}
|
||||
return {"session_id": session_id, "episodes": len(episodes), "promoted": [], "everos_backend": backend}
|
||||
return {
|
||||
"evermemos_backend": backend,
|
||||
"evermemos_error": error,
|
||||
"everos_backend": backend,
|
||||
"everos_error": error,
|
||||
"session_id": session_id,
|
||||
"episodes": result.episodes,
|
||||
"candidates": result.candidates,
|
||||
@ -252,24 +260,13 @@ class MemoryGatewayService:
|
||||
"review_drafts": result.review_drafts,
|
||||
}
|
||||
|
||||
def evermemos_health(self) -> dict:
|
||||
config = get_config().evermemos
|
||||
def everos_health(self) -> dict:
|
||||
config = get_config().everos
|
||||
if not config.enabled:
|
||||
return {"status": "disabled", "url": config.url}
|
||||
return (self.evermemos_client or EverMemOSClient()).health()
|
||||
|
||||
def _commit_session_locally(self, session_id: str, ctx: AccessContext, request: CommitSessionRequest):
|
||||
worker = EverMemOSWorker(self.repo)
|
||||
return worker.consolidate_session(
|
||||
session_id=session_id,
|
||||
ctx=ctx,
|
||||
min_importance=request.min_importance,
|
||||
target_namespace=request.target_namespace or user_long_term_namespace(request.user_id),
|
||||
)
|
||||
return (self.everos_client or EverOSClient()).health()
|
||||
|
||||
def _persist_external_consolidation(self, external_result: dict, ctx: AccessContext, session_id: str):
|
||||
from .workers.evermemos_worker import ConsolidationResult
|
||||
|
||||
result = ConsolidationResult(
|
||||
session_id=session_id,
|
||||
episodes=external_result.get("episodes") or len(self.repo.list_session_episodes(session_id)),
|
||||
@ -302,11 +299,11 @@ class MemoryGatewayService:
|
||||
data.setdefault("memory_type", MemoryType.SUMMARY.value)
|
||||
data.setdefault("content", data.get("text") or data.get("summary") or "")
|
||||
data.setdefault("summary", data.get("content", "")[:180])
|
||||
data.setdefault("tags", ["evermemos-external"])
|
||||
data.setdefault("tags", ["everos-external"])
|
||||
data.setdefault("importance", 0.7)
|
||||
data.setdefault("confidence", 0.65)
|
||||
data.setdefault("visibility", Visibility.PRIVATE.value)
|
||||
data.setdefault("source", SourceType.EVERMEMOS.value)
|
||||
data.setdefault("source", SourceType.EVEROS.value)
|
||||
if not data["content"]:
|
||||
return None
|
||||
return MemoryRecord.model_validate(data)
|
||||
|
||||
Reference in New Issue
Block a user