diff --git a/src/memos/graph_dbs/polardb.py b/src/memos/graph_dbs/polardb.py index 0ae4cfdb4..638eac9c2 100644 --- a/src/memos/graph_dbs/polardb.py +++ b/src/memos/graph_dbs/polardb.py @@ -503,7 +503,9 @@ def remove_oldest_memory( cursor.execute(delete_query, delete_params) deleted_count = cursor.rowcount logger.info( - f"Removed {deleted_count} oldest {memory_type} memories, keeping {keep_latest} latest for user {user_name}" + f"Removed {deleted_count} oldest {memory_type} memories, " + f"keeping {keep_latest} latest for user {user_name}, " + f"removed ids: {ids_to_delete}" ) except Exception as e: logger.error(f"[remove_oldest_memory] Failed: {e}", exc_info=True) @@ -2803,6 +2805,28 @@ def _parse_node(self, node_data: dict[str, Any]) -> dict[str, Any]: if time_field in node and hasattr(node[time_field], "isoformat"): node[time_field] = node[time_field].isoformat() + # Deserialize sources from JSON strings back to dict objects + if "sources" in node and node.get("sources"): + sources = node["sources"] + if isinstance(sources, list): + deserialized_sources = [] + for source_item in sources: + if isinstance(source_item, str): + # Try to parse JSON string + try: + parsed = json.loads(source_item) + deserialized_sources.append(parsed) + except (json.JSONDecodeError, TypeError): + # If parsing fails, keep as string or create a simple dict + deserialized_sources.append({"type": "doc", "content": source_item}) + elif isinstance(source_item, dict): + # Already a dict, keep as is + deserialized_sources.append(source_item) + else: + # Unknown type, create a simple dict + deserialized_sources.append({"type": "doc", "content": str(source_item)}) + node["sources"] = deserialized_sources + return {"id": node.get("id"), "memory": node.get("memory", ""), "metadata": node} def _parse_node_new(self, node_data: dict[str, Any]) -> dict[str, Any]: @@ -2835,6 +2859,28 @@ def _strip_wrapping_quotes(value: Any) -> Any: if time_field in node and hasattr(node[time_field], "isoformat"): node[time_field] = node[time_field].isoformat() + # Deserialize sources from JSON strings back to dict objects + if "sources" in node and node.get("sources"): + sources = node["sources"] + if isinstance(sources, list): + deserialized_sources = [] + for source_item in sources: + if isinstance(source_item, str): + # Try to parse JSON string + try: + parsed = json.loads(source_item) + deserialized_sources.append(parsed) + except (json.JSONDecodeError, TypeError): + # If parsing fails, keep as string or create a simple dict + deserialized_sources.append({"type": "doc", "content": source_item}) + elif isinstance(source_item, dict): + # Already a dict, keep as is + deserialized_sources.append(source_item) + else: + # Unknown type, create a simple dict + deserialized_sources.append({"type": "doc", "content": str(source_item)}) + node["sources"] = deserialized_sources + # Do not remove user_name; keep all fields return {"id": node.pop("id"), "memory": node.pop("memory", ""), "metadata": node}