diff --git a/backend/packages/harness/deerflow/utils/readability.py b/backend/packages/harness/deerflow/utils/readability.py index e25093aa87..d4aec84399 100644 --- a/backend/packages/harness/deerflow/utils/readability.py +++ b/backend/packages/harness/deerflow/utils/readability.py @@ -15,9 +15,10 @@ logger = logging.getLogger(__name__) class Article: url: str - def __init__(self, title: str, html_content: str): + def __init__(self, title: str, html_content: str, url: str | None = None): self.title = title self.html_content = html_content + self.url = url or "" def to_markdown(self, including_title: bool = True) -> str: markdown = "" @@ -176,4 +177,4 @@ class ReadabilityExtractor: if not title or not str(title).strip(): title = "Untitled" - return Article(title=title, html_content=html_content) + return Article(title=title, html_content=html_content, url=url) diff --git a/backend/tests/test_readability.py b/backend/tests/test_readability.py index f6b6e413d1..3a2341e8c1 100644 --- a/backend/tests/test_readability.py +++ b/backend/tests/test_readability.py @@ -4,7 +4,7 @@ import subprocess import pytest -from deerflow.utils.readability import ReadabilityExtractor +from deerflow.utils.readability import Article, ReadabilityExtractor def test_extract_article_falls_back_when_readability_js_fails(monkeypatch): @@ -53,3 +53,16 @@ def test_extract_article_re_raises_unexpected_exception(monkeypatch): with pytest.raises(RuntimeError, match="unexpected parser failure"): ReadabilityExtractor().extract_article("test") assert calls == [True] + + +def test_article_to_message_with_images(): + """Article.to_message should handle articles containing images without AttributeError.""" + # Absolute image URL without source url + art_abs = Article("Test Image", '') + msg_abs = art_abs.to_message() + assert any(block.get("type") == "image_url" and block["image_url"]["url"] == "https://example.com/pic.png" for block in msg_abs) + + # Relative image URL with source url + art_rel = Article("Test Relative Image", '', url="https://example.com/base/") + msg_rel = art_rel.to_message() + assert any(block.get("type") == "image_url" and block["image_url"]["url"] == "https://example.com/assets/pic.png" for block in msg_rel)