fix(server): fetch filtered dashboard memories beyond default page (#5753)
This commit is contained in:
@@ -27,6 +27,8 @@ import { useApiQuery } from "@/hooks/use-api-query";
|
||||
import { Memory } from "@/types/api";
|
||||
|
||||
const PAGE_SIZE = 20;
|
||||
// Keep in sync with ALL_MEMORIES_LIMIT in server/main.py.
|
||||
const MEMORY_FETCH_LIMIT = 1000;
|
||||
|
||||
export default function MemoriesPage() {
|
||||
const [userId, setUserId] = useState("");
|
||||
@@ -41,7 +43,9 @@ export default function MemoriesPage() {
|
||||
refetch,
|
||||
} = useApiQuery<Memory[]>(
|
||||
async () => {
|
||||
const params = userId.trim() ? { user_id: userId.trim() } : undefined;
|
||||
const params = userId.trim()
|
||||
? { user_id: userId.trim(), top_k: MEMORY_FETCH_LIMIT }
|
||||
: { top_k: MEMORY_FETCH_LIMIT };
|
||||
const res = await api.get(MEMORY_ENDPOINTS.BASE, { params });
|
||||
const raw = res.data?.results ?? res.data ?? [];
|
||||
return Array.isArray(raw) ? raw : [];
|
||||
@@ -96,7 +100,7 @@ export default function MemoriesPage() {
|
||||
<div className="space-y-4">
|
||||
<h1 className="text-xl font-semibold font-fustat">Memories</h1>
|
||||
|
||||
{memories.length >= 1000 && (
|
||||
{memories.length >= MEMORY_FETCH_LIMIT && (
|
||||
<UpgradeBanner
|
||||
id="memories-1k"
|
||||
message="1,000+ memories stored. Categories can help organize them."
|
||||
|
||||
+7
-3
@@ -16,7 +16,7 @@ from errors import (
|
||||
upstream_error,
|
||||
upstream_error_handler,
|
||||
)
|
||||
from fastapi import Depends, FastAPI, HTTPException, Request
|
||||
from fastapi import Depends, FastAPI, HTTPException, Query, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
from mem0.exceptions import ValidationError as Mem0ValidationError
|
||||
@@ -409,6 +409,7 @@ def get_all_memories(
|
||||
user_id: Optional[str] = None,
|
||||
run_id: Optional[str] = None,
|
||||
agent_id: Optional[str] = None,
|
||||
top_k: Optional[int] = Query(None, ge=0, le=ALL_MEMORIES_LIMIT),
|
||||
_auth=Depends(verify_auth),
|
||||
):
|
||||
"""Retrieve stored memories. Lists all memories when no identifier is provided (admin only)."""
|
||||
@@ -417,11 +418,14 @@ def get_all_memories(
|
||||
auth_type = getattr(request.state, "auth_type", "none")
|
||||
if _auth is not None and _auth.role != "admin" and auth_type not in {"admin_api_key", "disabled"}:
|
||||
raise HTTPException(status_code=403, detail="Admin role required to list all memories.")
|
||||
return _list_all_memories()
|
||||
return _list_all_memories(limit=top_k if top_k is not None else ALL_MEMORIES_LIMIT)
|
||||
filters = {
|
||||
k: v for k, v in {"user_id": user_id, "run_id": run_id, "agent_id": agent_id}.items() if v is not None
|
||||
}
|
||||
return get_memory_instance().get_all(filters=filters)
|
||||
params = {"filters": filters}
|
||||
if top_k is not None:
|
||||
params["top_k"] = top_k
|
||||
return get_memory_instance().get_all(**params)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception:
|
||||
|
||||
@@ -618,6 +618,31 @@ class TestGetMemories:
|
||||
# 3. Verify the core logic: the param was mapped to the filters dict!
|
||||
_, kwargs = mock_memory.get_all.call_args
|
||||
assert kwargs["filters"] == {"user_id": "test_routing_user"}
|
||||
assert "top_k" not in kwargs
|
||||
|
||||
def test_get_memories_entity_filters_forward_top_k(self, client, mock_memory):
|
||||
response = client.get("/memories?user_id=test_routing_user&top_k=1000")
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
_, kwargs = mock_memory.get_all.call_args
|
||||
assert kwargs["filters"] == {"user_id": "test_routing_user"}
|
||||
assert kwargs["top_k"] == 1000
|
||||
|
||||
def test_get_memories_admin_top_k_zero_not_defaulted(self, client, mock_memory):
|
||||
mock_memory.vector_store.list.return_value = []
|
||||
|
||||
response = client.get("/memories?top_k=0")
|
||||
|
||||
assert response.status_code == 200
|
||||
_, kwargs = mock_memory.vector_store.list.call_args
|
||||
assert kwargs["top_k"] == 0
|
||||
|
||||
def test_get_memories_rejects_top_k_above_limit(self, client, mock_memory):
|
||||
response = client.get("/memories?user_id=test_routing_user&top_k=1001")
|
||||
|
||||
assert response.status_code == 422
|
||||
mock_memory.get_all.assert_not_called()
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
|
||||
Reference in New Issue
Block a user