fix(server): fetch filtered dashboard memories beyond default page (#5753)

This commit is contained in:
冯基魁
2026-06-24 11:49:06 +05:30
committed by GitHub
parent 3497f26a00
commit 09f181c577
3 changed files with 38 additions and 5 deletions
@@ -27,6 +27,8 @@ import { useApiQuery } from "@/hooks/use-api-query";
import { Memory } from "@/types/api"; import { Memory } from "@/types/api";
const PAGE_SIZE = 20; const PAGE_SIZE = 20;
// Keep in sync with ALL_MEMORIES_LIMIT in server/main.py.
const MEMORY_FETCH_LIMIT = 1000;
export default function MemoriesPage() { export default function MemoriesPage() {
const [userId, setUserId] = useState(""); const [userId, setUserId] = useState("");
@@ -41,7 +43,9 @@ export default function MemoriesPage() {
refetch, refetch,
} = useApiQuery<Memory[]>( } = useApiQuery<Memory[]>(
async () => { 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 res = await api.get(MEMORY_ENDPOINTS.BASE, { params });
const raw = res.data?.results ?? res.data ?? []; const raw = res.data?.results ?? res.data ?? [];
return Array.isArray(raw) ? raw : []; return Array.isArray(raw) ? raw : [];
@@ -96,7 +100,7 @@ export default function MemoriesPage() {
<div className="space-y-4"> <div className="space-y-4">
<h1 className="text-xl font-semibold font-fustat">Memories</h1> <h1 className="text-xl font-semibold font-fustat">Memories</h1>
{memories.length >= 1000 && ( {memories.length >= MEMORY_FETCH_LIMIT && (
<UpgradeBanner <UpgradeBanner
id="memories-1k" id="memories-1k"
message="1,000+ memories stored. Categories can help organize them." message="1,000+ memories stored. Categories can help organize them."
+7 -3
View File
@@ -16,7 +16,7 @@ from errors import (
upstream_error, upstream_error,
upstream_error_handler, 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.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, RedirectResponse from fastapi.responses import JSONResponse, RedirectResponse
from mem0.exceptions import ValidationError as Mem0ValidationError from mem0.exceptions import ValidationError as Mem0ValidationError
@@ -409,6 +409,7 @@ def get_all_memories(
user_id: Optional[str] = None, user_id: Optional[str] = None,
run_id: Optional[str] = None, run_id: Optional[str] = None,
agent_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), _auth=Depends(verify_auth),
): ):
"""Retrieve stored memories. Lists all memories when no identifier is provided (admin only).""" """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") 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"}: 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.") 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 = { 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 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: except HTTPException:
raise raise
except Exception: except Exception:
+25
View File
@@ -618,6 +618,31 @@ class TestGetMemories:
# 3. Verify the core logic: the param was mapped to the filters dict! # 3. Verify the core logic: the param was mapped to the filters dict!
_, kwargs = mock_memory.get_all.call_args _, kwargs = mock_memory.get_all.call_args
assert kwargs["filters"] == {"user_id": "test_routing_user"} 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()
# =========================================================================== # ===========================================================================