Add memory management APIs for OpenViking: list, read, write, and delete memories
This commit is contained in:
@ -5,6 +5,7 @@ from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
|
||||
from .auth import verify_api_key
|
||||
from .schemas import (
|
||||
MemoryWriteRequest,
|
||||
MessageIngestRequest,
|
||||
ProfileRequest,
|
||||
ResourceUploadRequest,
|
||||
@ -80,6 +81,58 @@ async def delete_resource(
|
||||
raise user_auth_error(exc) from exc
|
||||
|
||||
|
||||
@router.get("/memories")
|
||||
async def list_memories(
|
||||
user_id: str = Query(min_length=1),
|
||||
user_key: str = Query(min_length=1),
|
||||
uri: str = Query(default="viking://user/memories", min_length=1),
|
||||
recursive: bool = Query(default=True),
|
||||
service: MemorySystemService = Depends(get_service),
|
||||
):
|
||||
try:
|
||||
return await service.list_memories(user_id, user_key, uri=uri, recursive=recursive)
|
||||
except PermissionError as exc:
|
||||
raise user_auth_error(exc) from exc
|
||||
|
||||
|
||||
@router.get("/memories/content")
|
||||
async def read_memory(
|
||||
user_id: str = Query(min_length=1),
|
||||
user_key: str = Query(min_length=1),
|
||||
uri: str = Query(min_length=1),
|
||||
service: MemorySystemService = Depends(get_service),
|
||||
):
|
||||
try:
|
||||
return await service.read_memory(user_id, user_key, uri)
|
||||
except PermissionError as exc:
|
||||
raise user_auth_error(exc) from exc
|
||||
|
||||
|
||||
@router.post("/memories")
|
||||
async def write_memory(
|
||||
request: MemoryWriteRequest,
|
||||
service: MemorySystemService = Depends(get_service),
|
||||
):
|
||||
try:
|
||||
return await service.write_memory(request)
|
||||
except PermissionError as exc:
|
||||
raise user_auth_error(exc) from exc
|
||||
|
||||
|
||||
@router.delete("/memories")
|
||||
async def delete_memory(
|
||||
user_id: str = Query(min_length=1),
|
||||
user_key: str = Query(min_length=1),
|
||||
uri: str = Query(min_length=1),
|
||||
recursive: bool = Query(default=False),
|
||||
service: MemorySystemService = Depends(get_service),
|
||||
):
|
||||
try:
|
||||
return await service.delete_memory(user_id, user_key, uri, recursive=recursive)
|
||||
except PermissionError as exc:
|
||||
raise user_auth_error(exc) from exc
|
||||
|
||||
|
||||
@router.post("/sessions/{session_id}/commit")
|
||||
async def commit_session(
|
||||
session_id: str,
|
||||
|
||||
@ -190,6 +190,62 @@ class OpenVikingMemorySystemClient:
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def list_memories(
|
||||
self,
|
||||
credential: OpenVikingCredential | str,
|
||||
uri: str = "viking://user/memories",
|
||||
recursive: bool = True,
|
||||
) -> dict[str, Any]:
|
||||
async with self._credential_client(credential) as client:
|
||||
response = await client.get(
|
||||
"/api/v1/fs/ls",
|
||||
params={"uri": uri, "recursive": str(recursive).lower()},
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def read_memory(self, credential: OpenVikingCredential | str, uri: str) -> dict[str, Any]:
|
||||
async with self._credential_client(credential) as client:
|
||||
response = await client.get("/api/v1/content/read", params={"uri": uri})
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def write_memory(
|
||||
self,
|
||||
credential: OpenVikingCredential | str,
|
||||
*,
|
||||
uri: str,
|
||||
content: str,
|
||||
mode: str = "create",
|
||||
wait: bool = True,
|
||||
) -> dict[str, Any]:
|
||||
async with self._credential_client(credential) as client:
|
||||
response = await client.post(
|
||||
"/api/v1/content/write",
|
||||
json={
|
||||
"uri": uri,
|
||||
"content": content,
|
||||
"mode": mode,
|
||||
"wait": wait,
|
||||
},
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def delete_memory(
|
||||
self,
|
||||
credential: OpenVikingCredential | str,
|
||||
uri: str,
|
||||
recursive: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
async with self._credential_client(credential) as client:
|
||||
response = await client.delete(
|
||||
"/api/v1/fs",
|
||||
params={"uri": uri, "recursive": str(recursive).lower()},
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def find(self, credential: OpenVikingCredential | str, query: str, limit: int) -> dict[str, Any]:
|
||||
user_id = credential.user_id if isinstance(credential, OpenVikingCredential) else None
|
||||
target_uri = f"viking://user/{user_id}/memories/" if user_id else "viking://user/memories/"
|
||||
|
||||
@ -7,6 +7,7 @@ from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
OperationStatus = Literal["success", "partial_success", "failed"]
|
||||
MemoryWriteMode = Literal["create", "replace", "append"]
|
||||
|
||||
|
||||
class MessageIngestRequest(BaseModel):
|
||||
@ -54,6 +55,15 @@ class ProfileRequest(BaseModel):
|
||||
level: int = Field(default=2, ge=0)
|
||||
|
||||
|
||||
class MemoryWriteRequest(BaseModel):
|
||||
user_id: str = Field(min_length=1)
|
||||
user_key: str = Field(min_length=1)
|
||||
uri: str = Field(min_length=1)
|
||||
content: str
|
||||
mode: MemoryWriteMode = "create"
|
||||
wait: bool = True
|
||||
|
||||
|
||||
class ResourceUploadRequest(BaseModel):
|
||||
user_id: str = Field(min_length=1)
|
||||
user_key: str = Field(min_length=1)
|
||||
@ -116,6 +126,12 @@ class ProfileResponse(BaseModel):
|
||||
backends: dict[str, BackendStatus]
|
||||
|
||||
|
||||
class MemoryOperationResponse(BaseModel):
|
||||
status: OperationStatus
|
||||
memory: Any = None
|
||||
backends: dict[str, BackendStatus]
|
||||
|
||||
|
||||
class ResourceMutationResponse(BaseModel):
|
||||
status: OperationStatus
|
||||
resource: Any = None
|
||||
|
||||
@ -11,6 +11,8 @@ from .schemas import (
|
||||
BackendStatus,
|
||||
CommitResponse,
|
||||
ExtractResponse,
|
||||
MemoryOperationResponse,
|
||||
MemoryWriteRequest,
|
||||
MessageIngestRequest,
|
||||
MessageIngestResponse,
|
||||
ProfileResponse,
|
||||
@ -76,6 +78,63 @@ class MemorySystemService:
|
||||
resource = backends["openviking"].result if backends["openviking"].status == "success" else None
|
||||
return ResourceMutationResponse(status=self._aggregate_status(backends), resource=resource, backends=backends)
|
||||
|
||||
async def list_memories(
|
||||
self,
|
||||
user_id: str,
|
||||
user_key: str,
|
||||
uri: str = "viking://user/memories",
|
||||
recursive: bool = True,
|
||||
) -> MemoryOperationResponse:
|
||||
credential = self.openviking.credential_for_user(user_id, user_key)
|
||||
backends = {
|
||||
"openviking": await self._capture(lambda: self.openviking.list_memories(credential, uri, recursive)),
|
||||
}
|
||||
memory = backends["openviking"].result if backends["openviking"].status == "success" else None
|
||||
return MemoryOperationResponse(status=self._aggregate_status(backends), memory=memory, backends=backends)
|
||||
|
||||
async def read_memory(
|
||||
self,
|
||||
user_id: str,
|
||||
user_key: str,
|
||||
uri: str,
|
||||
) -> MemoryOperationResponse:
|
||||
credential = self.openviking.credential_for_user(user_id, user_key)
|
||||
backends = {
|
||||
"openviking": await self._capture(lambda: self.openviking.read_memory(credential, uri)),
|
||||
}
|
||||
memory = backends["openviking"].result if backends["openviking"].status == "success" else None
|
||||
return MemoryOperationResponse(status=self._aggregate_status(backends), memory=memory, backends=backends)
|
||||
|
||||
async def write_memory(self, request: MemoryWriteRequest) -> MemoryOperationResponse:
|
||||
credential = self.openviking.credential_for_user(request.user_id, request.user_key)
|
||||
backends = {
|
||||
"openviking": await self._capture(
|
||||
lambda: self.openviking.write_memory(
|
||||
credential,
|
||||
uri=request.uri,
|
||||
content=request.content,
|
||||
mode=request.mode,
|
||||
wait=request.wait,
|
||||
)
|
||||
),
|
||||
}
|
||||
memory = backends["openviking"].result if backends["openviking"].status == "success" else None
|
||||
return MemoryOperationResponse(status=self._aggregate_status(backends), memory=memory, backends=backends)
|
||||
|
||||
async def delete_memory(
|
||||
self,
|
||||
user_id: str,
|
||||
user_key: str,
|
||||
uri: str,
|
||||
recursive: bool = False,
|
||||
) -> MemoryOperationResponse:
|
||||
credential = self.openviking.credential_for_user(user_id, user_key)
|
||||
backends = {
|
||||
"openviking": await self._capture(lambda: self.openviking.delete_memory(credential, uri, recursive)),
|
||||
}
|
||||
memory = backends["openviking"].result if backends["openviking"].status == "success" else None
|
||||
return MemoryOperationResponse(status=self._aggregate_status(backends), memory=memory, backends=backends)
|
||||
|
||||
async def ingest_messages(self, request: MessageIngestRequest) -> MessageIngestResponse:
|
||||
messages = self._messages_from_request(request)
|
||||
if not messages:
|
||||
|
||||
Reference in New Issue
Block a user