diff --git a/docker/requirements.txt b/docker/requirements.txt index 988e64b83..afbcd4d26 100644 --- a/docker/requirements.txt +++ b/docker/requirements.txt @@ -98,6 +98,7 @@ rich-toolkit==0.15.1 rignore==0.7.6 rpds-py==0.28.0 safetensors==0.6.2 +schedule==1.2.2 scikit-learn==1.7.2 scipy==1.16.3 sentry-sdk==2.44.0 diff --git a/src/memos/graph_dbs/neo4j_community.py b/src/memos/graph_dbs/neo4j_community.py index b5c92f40a..cf0a89f81 100644 --- a/src/memos/graph_dbs/neo4j_community.py +++ b/src/memos/graph_dbs/neo4j_community.py @@ -225,6 +225,28 @@ def add_nodes_batch(self, nodes: list[dict[str, Any]], user_name: str | None = N logger.error(f"[add_nodes_batch] Failed to add nodes: {e}", exc_info=True) raise + def update_node(self, id: str, fields: dict[str, Any], user_name: str | None = None) -> None: + """ + Update node in Neo4j and sync key fields to Qdrant payload. + + The parent implementation only updates Neo4j. For the community edition, which + relies on an external vector DB (Qdrant), key status/metadata fields must also + be propagated to the Qdrant payload so that vector searches reflect the latest + node state (e.g. archived memories are excluded correctly). + """ + super().update_node(id, fields, user_name) + + sync_fields = {"status", "tags", "memory_type", "content", "sources"} + payload_updates = {k: v for k, v in fields.items() if k in sync_fields} + if payload_updates and self.vec_db: + try: + self.vec_db.update(id, VecDBItem(id=id, vector=None, payload=payload_updates)) + except Exception as e: + logger.warning( + f"[update_node] Failed to sync fields {list(payload_updates)} " + f"to Qdrant for node {id}: {e}" + ) + def get_children_with_embeddings( self, id: str, user_name: str | None = None ) -> list[dict[str, Any]]: