Replace EverMemOS with EverOS backend

This commit is contained in:
2026-05-13 17:56:50 +08:00
parent 0acee1ec6c
commit b226749c61
37 changed files with 1327 additions and 1986 deletions

View File

@ -1,7 +1,6 @@
"""OpenViking client wrapper used by Memory Gateway."""
from __future__ import annotations
import json
import logging
import mimetypes
import tempfile
@ -58,6 +57,7 @@ class OpenVikingClient:
headers = {}
if self.api_key:
headers["X-API-Key"] = self.api_key
headers["Authorization"] = f"Bearer {self.api_key}"
headers["X-OpenViking-Account"] = self.account
headers["X-OpenViking-User"] = self.user
return headers
@ -190,36 +190,64 @@ class OpenVikingClient:
return self._normalize_commit_response(raw)
async def retrieve_context_v2(self, payload: dict[str, Any]) -> BackendRetrieveResult:
"""v2 adapter placeholder for OpenViking runtime context retrieval.
Mapping spec: retrieve_context returns BackendRetrieveResult with
runtime context items, not raw backend payload dumps.
"""
raw = {
"status": "ok",
"session_id": payload.get("session_id"),
"metadata": {
"reason": "openviking_v2_retrieve_fixture",
"schema_version": "openviking.fixture.retrieve.v2",
},
"result": {
"items": [
{
"text": "OpenViking fixture runtime context.",
"ref_id": f"ov_context:{payload.get('session_id') or 'unknown'}",
"score": 0.75,
"memory_type": "context_resource",
"metadata": {"schema_version": "openviking.fixture.retrieve.item.v2"},
}
]
},
}
return self._normalize_retrieve_response(raw)
Calls OpenViking native API to retrieve context.
Uses POST /search
"""
if not self._use_real_api:
return BackendRetrieveResult(
backend_type=BackendType.OPENVIKING,
operation=BackendOperation.RETRIEVE_CONTEXT,
status=BackendResultStatus.SKIPPED,
items=[],
metadata={"reason": "openviking_retrieve_requires_real_mode"},
)
query = payload.get("query", "")
session_id = payload.get("session_id")
request_data = {"query": query, "limit": 10}
if session_id:
request_data["session_id"] = session_id
try:
client = await self._get_client()
response = await client.post("/api/v1/search/search", json=request_data)
if response.status_code >= 400:
return BackendRetrieveResult(
backend_type=BackendType.OPENVIKING,
operation=BackendOperation.RETRIEVE_CONTEXT,
status=BackendResultStatus.FAILED,
items=[],
error_code=f"http_{response.status_code}",
error_message=f"OpenViking search failed: {response.text}",
retryable=False
)
return self._normalize_retrieve_response(response.json())
except Exception as exc:
return BackendRetrieveResult(
backend_type=BackendType.OPENVIKING,
operation=BackendOperation.RETRIEVE_CONTEXT,
status=BackendResultStatus.FAILED,
items=[],
error_code="request_error",
error_message=str(exc),
retryable=True
)
def _build_ingest_payload(self, payload: dict[str, Any]) -> dict[str, Any]:
# Runtime-only adapter payload. It may include conversation content for
# the current request lifecycle; callers must not persist it to SQLite.
return dict(payload)
"""
Build payload for native OpenViking AddMessageRequest.
OpenViking only expects role and content, and maybe metadata.
"""
return {
"role": payload.get("role", "user"),
"content": payload.get("content", ""),
"metadata": payload.get("metadata", {}),
"session_id": payload.get("session_id") # kept so format_ingest_path can use it
}
def _format_ingest_path(self, payload: dict[str, Any]) -> str:
session_id = str(payload.get("session_id") or "unknown")
@ -277,9 +305,9 @@ class OpenVikingClient:
payload["limit"] = limit
if uri:
payload["uri"] = uri
payload["target_uri"] = uri
elif namespace:
payload["uri"] = f"viking://{namespace}"
payload["target_uri"] = f"viking://{namespace}"
try:
response = await client.post("/api/v1/search/search", json=payload)
@ -321,7 +349,7 @@ class OpenVikingClient:
ns = namespace or self.config.memory.default_namespace or "user/default/memories"
try:
response = await client.post("/api/v1/sessions", json={"mode": "interactive"})
response = await client.post("/api/v1/sessions")
response.raise_for_status()
session_data = response.json()
@ -329,17 +357,15 @@ class OpenVikingClient:
return session_data
session_id = session_data["result"]["session_id"]
commit_response = await client.post(
f"/api/v1/sessions/{session_id}/commit",
message_response = await client.post(
f"/api/v1/sessions/{session_id}/messages",
json={
"messages": [
{
"role": "user",
"content": f"[{ns}/{memory_type}] {content}",
}
]
"role": "user",
"content": f"[{ns}/{memory_type}] {content}",
},
)
message_response.raise_for_status()
commit_response = await client.post(f"/api/v1/sessions/{session_id}/commit")
commit_response.raise_for_status()
return commit_response.json()
except httpx.HTTPError as e:
@ -396,7 +422,6 @@ class OpenVikingClient:
"temp_path": temp_ref,
"to": uri,
"wait": wait,
"source_name": Path(uri).name or tmp_path.name,
"strict": False,
}
response = await client.post("/api/v1/resources", json=payload)
@ -425,7 +450,7 @@ class OpenVikingClient:
try:
response = await client.post(
"/api/v1/search/search",
json={"query": "", "uri": f"viking://{ns}", "limit": limit or 10},
json={"query": "", "target_uri": f"viking://{ns}", "limit": limit or 10},
)
response.raise_for_status()
data = response.json()
@ -458,7 +483,7 @@ class OpenVikingClient:
try:
response = await client.post(
"/api/v1/search/search",
json={"query": "", "uri": uri, "limit": limit or 10},
json={"query": "", "target_uri": uri, "limit": limit or 10},
)
response.raise_for_status()
data = response.json()