Replace EverMemOS with EverOS backend
This commit is contained in:
@ -12,13 +12,14 @@ from .backend_contracts import (
|
||||
BackendOperation,
|
||||
BackendCommitResult,
|
||||
BackendProducedRef,
|
||||
BackendRetrieveResult,
|
||||
BackendResultStatus,
|
||||
BackendWriteResult,
|
||||
CommitJob,
|
||||
OutboxEvent,
|
||||
OutboxEventStatus,
|
||||
)
|
||||
from .evermemos_client import EverMemOSClient
|
||||
from .everos_client import EverOSClient
|
||||
from .openviking_client import get_openviking_client
|
||||
from .repositories import MetadataRepository, repository
|
||||
from .schemas import AuditLog
|
||||
@ -52,11 +53,11 @@ class MemoryGatewayV2Service:
|
||||
self,
|
||||
repo: MetadataRepository = repository,
|
||||
openviking_client_factory: OpenVikingClientFactory = get_openviking_client,
|
||||
evermemos_client: Any | None = None,
|
||||
everos_client: Any | None = None,
|
||||
) -> None:
|
||||
self.repo = repo
|
||||
self.openviking_client_factory = openviking_client_factory
|
||||
self.evermemos_client = evermemos_client
|
||||
self.everos_client = everos_client
|
||||
|
||||
async def ingest_conversation_turn(self, request: IngestRequest) -> IngestResponse:
|
||||
normalized = self._normalize_ingest_request(request)
|
||||
@ -92,9 +93,9 @@ class MemoryGatewayV2Service:
|
||||
)
|
||||
)
|
||||
|
||||
if normalized.policy.allow_evermemos:
|
||||
if normalized.policy.allow_everos:
|
||||
refs.append(
|
||||
await self._write_evermemos_message(
|
||||
await self._write_everos_message(
|
||||
normalized,
|
||||
payload,
|
||||
gateway_id=gateway_id,
|
||||
@ -108,7 +109,7 @@ class MemoryGatewayV2Service:
|
||||
normalized,
|
||||
gateway_id,
|
||||
provenance_id,
|
||||
BackendType.EVERMEMOS,
|
||||
BackendType.EVEROS,
|
||||
MemoryRefType.MESSAGE_MEMORY,
|
||||
BackendRefStatus.SKIPPED,
|
||||
content_hash=content_hash,
|
||||
@ -188,8 +189,21 @@ class MemoryGatewayV2Service:
|
||||
)
|
||||
|
||||
async def retrieve_context(self, request: RetrieveRequest) -> RetrieveResponse:
|
||||
# TODO(v2): expand namespace ACL, fan out concurrently to OpenViking and
|
||||
# EverMemOS, then apply lightweight merge/rerank before returning.
|
||||
payload = {
|
||||
"workspace_id": request.workspace_id,
|
||||
"user_id": request.user_id,
|
||||
"agent_id": request.agent_id,
|
||||
"session_id": request.session_id,
|
||||
"namespace": request.namespace,
|
||||
"query": request.query,
|
||||
"limit": request.limit,
|
||||
"metadata": request.metadata,
|
||||
}
|
||||
results = [
|
||||
await self._retrieve_openviking_context(payload),
|
||||
await self._retrieve_everos_context(payload),
|
||||
]
|
||||
items = self._merge_retrieve_items(results, limit=request.limit)
|
||||
refs = self.repo.list_memory_refs(
|
||||
workspace_id=request.workspace_id,
|
||||
user_id=request.user_id,
|
||||
@ -198,21 +212,6 @@ class MemoryGatewayV2Service:
|
||||
namespace=request.namespace,
|
||||
limit=request.limit,
|
||||
)
|
||||
items = [
|
||||
ContextItem(
|
||||
text=None,
|
||||
source_backend=ref.backend_type,
|
||||
ref_id=ref.id,
|
||||
score=0.0,
|
||||
memory_type=ref.ref_type.value,
|
||||
metadata={
|
||||
"status": ref.status.value,
|
||||
"native_id": ref.native_id,
|
||||
"native_uri": ref.native_uri,
|
||||
},
|
||||
)
|
||||
for ref in refs
|
||||
]
|
||||
trace_id = request.metadata.get("trace_id") if request.metadata else None
|
||||
return RetrieveResponse(
|
||||
status=OperationStatus.SUCCESS,
|
||||
@ -220,7 +219,7 @@ class MemoryGatewayV2Service:
|
||||
refs=self._view_refs(refs),
|
||||
conflicts=[],
|
||||
trace_id=trace_id,
|
||||
metadata={"skeleton": True},
|
||||
metadata=self._retrieve_metadata(results),
|
||||
)
|
||||
|
||||
async def record_memory_feedback(self, request: FeedbackRequest) -> FeedbackResponse:
|
||||
@ -386,6 +385,83 @@ class MemoryGatewayV2Service:
|
||||
limit=limit,
|
||||
)
|
||||
|
||||
async def _retrieve_openviking_context(self, payload: dict[str, Any]) -> BackendRetrieveResult:
|
||||
try:
|
||||
client = await self.openviking_client_factory()
|
||||
if not hasattr(client, "retrieve_context_v2"):
|
||||
return BackendRetrieveResult(
|
||||
backend_type=BackendType.OPENVIKING,
|
||||
status=BackendResultStatus.SKIPPED,
|
||||
metadata={"reason": "adapter_method_missing"},
|
||||
)
|
||||
result = client.retrieve_context_v2(payload)
|
||||
if hasattr(result, "__await__"):
|
||||
result = await result
|
||||
return result
|
||||
except Exception as exc: # noqa: BLE001
|
||||
return BackendRetrieveResult(
|
||||
backend_type=BackendType.OPENVIKING,
|
||||
status=BackendResultStatus.FAILED,
|
||||
error_code="adapter_exception",
|
||||
error_message=str(exc),
|
||||
retryable=True,
|
||||
)
|
||||
|
||||
async def _retrieve_everos_context(self, payload: dict[str, Any]) -> BackendRetrieveResult:
|
||||
try:
|
||||
client = self.everos_client or EverOSClient()
|
||||
if not hasattr(client, "retrieve_context_v2"):
|
||||
return BackendRetrieveResult(
|
||||
backend_type=BackendType.EVEROS,
|
||||
status=BackendResultStatus.SKIPPED,
|
||||
metadata={"reason": "adapter_method_missing"},
|
||||
)
|
||||
result = client.retrieve_context_v2(payload)
|
||||
if hasattr(result, "__await__"):
|
||||
result = await result
|
||||
return result
|
||||
except Exception as exc: # noqa: BLE001
|
||||
return BackendRetrieveResult(
|
||||
backend_type=BackendType.EVEROS,
|
||||
status=BackendResultStatus.FAILED,
|
||||
error_code="adapter_exception",
|
||||
error_message=str(exc),
|
||||
retryable=True,
|
||||
)
|
||||
|
||||
def _merge_retrieve_items(self, results: list[BackendRetrieveResult], limit: int) -> list[ContextItem]:
|
||||
items: list[ContextItem] = []
|
||||
for result in results:
|
||||
if result.status != BackendResultStatus.SUCCESS:
|
||||
continue
|
||||
for item in result.items:
|
||||
items.append(
|
||||
ContextItem(
|
||||
text=item.text,
|
||||
source_backend=item.source_backend,
|
||||
ref_id=item.ref_id,
|
||||
score=item.score,
|
||||
memory_type=item.memory_type,
|
||||
metadata=item.metadata,
|
||||
)
|
||||
)
|
||||
items.sort(key=lambda item: item.score, reverse=True)
|
||||
return items[:limit]
|
||||
|
||||
def _retrieve_metadata(self, results: list[BackendRetrieveResult]) -> dict[str, Any]:
|
||||
return {
|
||||
"backend_results": [
|
||||
{
|
||||
"backend_type": result.backend_type.value,
|
||||
"status": result.status.value,
|
||||
"items": len(result.items),
|
||||
"error_code": result.error_code,
|
||||
"error_message": result.error_message,
|
||||
}
|
||||
for result in results
|
||||
]
|
||||
}
|
||||
|
||||
async def _execute_outbox_event(self, event: OutboxEvent) -> BackendCommitResult | BackendWriteResult:
|
||||
payload = self._outbox_payload(event)
|
||||
if event.operation != BackendOperation.COMMIT_SESSION:
|
||||
@ -406,11 +482,11 @@ class MemoryGatewayV2Service:
|
||||
)
|
||||
result = await client.commit_session_v2(payload)
|
||||
return result
|
||||
if event.backend_type == BackendType.EVERMEMOS:
|
||||
client = self.evermemos_client or EverMemOSClient()
|
||||
if event.backend_type == BackendType.EVEROS:
|
||||
client = self.everos_client or EverOSClient()
|
||||
if not hasattr(client, "extract_profile_long_term_v2"):
|
||||
return BackendCommitResult(
|
||||
backend_type=BackendType.EVERMEMOS,
|
||||
backend_type=event.backend_type,
|
||||
operation=BackendOperation.COMMIT_SESSION,
|
||||
status=BackendResultStatus.SKIPPED,
|
||||
metadata={"reason": "adapter_method_missing"},
|
||||
@ -557,7 +633,7 @@ class MemoryGatewayV2Service:
|
||||
pass
|
||||
if event.backend_type == BackendType.OPENVIKING:
|
||||
return MemoryRefType.SESSION_ARCHIVE
|
||||
if event.backend_type == BackendType.EVERMEMOS:
|
||||
if event.backend_type == BackendType.EVEROS:
|
||||
return MemoryRefType.LONG_TERM_MEMORY
|
||||
return MemoryRefType.DRAFT_REVIEW
|
||||
|
||||
@ -712,7 +788,7 @@ class MemoryGatewayV2Service:
|
||||
metadata=self._control_metadata(request, content_hash),
|
||||
)
|
||||
|
||||
async def _write_evermemos_message(
|
||||
async def _write_everos_message(
|
||||
self,
|
||||
request: IngestRequest,
|
||||
payload: dict[str, Any],
|
||||
@ -721,13 +797,13 @@ class MemoryGatewayV2Service:
|
||||
content_hash: str,
|
||||
) -> MemoryRef:
|
||||
try:
|
||||
client = self.evermemos_client or EverMemOSClient()
|
||||
client = self.everos_client or EverOSClient()
|
||||
if not hasattr(client, "ingest_message"):
|
||||
return self._save_ref(
|
||||
request,
|
||||
gateway_id,
|
||||
provenance_id,
|
||||
BackendType.EVERMEMOS,
|
||||
BackendType.EVEROS,
|
||||
MemoryRefType.MESSAGE_MEMORY,
|
||||
BackendRefStatus.SKIPPED,
|
||||
content_hash=content_hash,
|
||||
@ -740,7 +816,7 @@ class MemoryGatewayV2Service:
|
||||
request,
|
||||
gateway_id,
|
||||
provenance_id,
|
||||
BackendType.EVERMEMOS,
|
||||
BackendType.EVEROS,
|
||||
MemoryRefType.MESSAGE_MEMORY,
|
||||
result,
|
||||
content_hash,
|
||||
@ -750,7 +826,7 @@ class MemoryGatewayV2Service:
|
||||
request,
|
||||
gateway_id,
|
||||
provenance_id,
|
||||
BackendType.EVERMEMOS,
|
||||
BackendType.EVEROS,
|
||||
MemoryRefType.MESSAGE_MEMORY,
|
||||
BackendRefStatus.FAILED,
|
||||
content_hash=content_hash,
|
||||
@ -946,7 +1022,7 @@ class MemoryGatewayV2Service:
|
||||
"idempotency_key": request.idempotency_key,
|
||||
"request_id": request.request_id,
|
||||
}
|
||||
for backend_type in (BackendType.OPENVIKING, BackendType.EVERMEMOS):
|
||||
for backend_type in (BackendType.OPENVIKING, BackendType.EVEROS):
|
||||
event = OutboxEvent(
|
||||
id=self._outbox_event_id(gateway_id, backend_type, BackendOperation.COMMIT_SESSION),
|
||||
event_type="commit_session",
|
||||
|
||||
Reference in New Issue
Block a user