diff --git a/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/message_processing.py b/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/message_processing.py index e482cabe1f..d9d55aee4a 100644 --- a/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/message_processing.py +++ b/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/message_processing.py @@ -97,6 +97,13 @@ def load_patterns(name: str, *, patterns_dir: str | None = None) -> list[re.Patt def extract_message_text(message: Any) -> str: """Extract plain text from message content for filtering and signal detection.""" content = getattr(message, "content", "") + if content is None: + # ``str(None)`` is the truthy literal ``"None"``, so a content-less + # message would survive every downstream ``text if text else ...`` + # fallback and be reported as real user text. Keep this in step with + # ``deerflow/utils/messages.py:message_content_to_text`` and the mem0 + # copy of this helper, which both return "" here. + return "" if isinstance(content, list): text_parts: list[str] = [] for part in content: diff --git a/backend/tests/test_message_processing_signals.py b/backend/tests/test_message_processing_signals.py index 5d32f1203b..33ecaffec2 100644 --- a/backend/tests/test_message_processing_signals.py +++ b/backend/tests/test_message_processing_signals.py @@ -137,3 +137,19 @@ def test_prepare_update_returns_new_signals_after_swap(tmp_path) -> None: _filtered, signals = r assert "preference" in signals assert len(_filtered) == 2 # not trivial -> kept + + +# ── extract_message_text: content shapes ─────────────────────────────────── + + +def test_extract_message_text_treats_none_as_empty() -> None: + """A content-less message must not become the literal string ``"None"``. + + ``str(None)`` is truthy, so the naive fallback would hand ``"None"`` to + signal detection and to the memory-update prompt as if it were real user + text. Mirrors ``utils/messages.py:message_content_to_text`` and + ``test_mem0_memory_backend.py::test_extract_message_text_treats_none_as_empty``. + """ + msg = _human("") + msg.content = None + assert extract_message_text(msg) == ""