mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Merge d999f35eb5 into fd10463069
This commit is contained in:
commit
ba923479bb
2 changed files with 118 additions and 0 deletions
|
|
@ -530,6 +530,8 @@ class SignalAdapter(BasePlatformAdapter):
|
|||
msg_type = MessageType.VOICE
|
||||
elif any(mt.startswith("image/") for mt in media_types):
|
||||
msg_type = MessageType.PHOTO
|
||||
elif any(mt.startswith("application/") or mt.startswith("text/") for mt in media_types):
|
||||
msg_type = MessageType.DOCUMENT
|
||||
|
||||
# Parse timestamp from envelope data (milliseconds since epoch)
|
||||
ts_ms = envelope_data.get("timestamp", 0)
|
||||
|
|
|
|||
|
|
@ -760,6 +760,122 @@ class TestSignalMediaExtraction:
|
|||
assert type(adapter).send_image is not BasePlatformAdapter.send_image
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Inbound attachment message type classification
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _make_dm_envelope(sender: str, attachments: list, text: str = "") -> dict:
|
||||
"""Build a minimal signal-cli DM envelope with the given attachments."""
|
||||
return {
|
||||
"envelope": {
|
||||
"sourceNumber": sender,
|
||||
"sourceName": "Test User",
|
||||
"sourceUuid": "aaaaaaaa-0000-0000-0000-000000000001",
|
||||
"timestamp": 1700000000000,
|
||||
"dataMessage": {
|
||||
"timestamp": 1700000000000,
|
||||
"message": text,
|
||||
"expiresInSeconds": 0,
|
||||
"viewOnce": False,
|
||||
"attachments": attachments,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestSignalInboundMessageTypeClassification:
|
||||
"""_handle_envelope must set MessageType.DOCUMENT for application/* and text/* attachments.
|
||||
|
||||
Before the fix, PDFs and other documents left msg_type as MessageType.TEXT,
|
||||
so run.py's document-context injection (which gates on MessageType.DOCUMENT)
|
||||
silently dropped the file and the agent never saw it.
|
||||
"""
|
||||
|
||||
async def _dispatch_single_attachment(self, monkeypatch, content_type: str,
|
||||
att_id: str, fetch_path: str, fetch_ext: str):
|
||||
"""Helper: run _handle_envelope with one attachment and return the dispatched event."""
|
||||
envelope = _make_dm_envelope(
|
||||
sender="+15559876543",
|
||||
attachments=[{
|
||||
"contentType": content_type,
|
||||
"id": att_id,
|
||||
"size": 1024,
|
||||
"filename": None,
|
||||
"width": None,
|
||||
"height": None,
|
||||
"caption": None,
|
||||
"uploadTimestamp": 1700000000000,
|
||||
}],
|
||||
)
|
||||
adapter = _make_signal_adapter(monkeypatch)
|
||||
adapter._rpc, _ = _stub_rpc(None)
|
||||
dispatched = []
|
||||
|
||||
async def _fake_handle_message(event):
|
||||
dispatched.append(event)
|
||||
|
||||
adapter.handle_message = _fake_handle_message
|
||||
adapter._fetch_attachment = AsyncMock(return_value=(fetch_path, fetch_ext))
|
||||
await adapter._handle_envelope(envelope)
|
||||
assert dispatched, "_handle_envelope did not dispatch any event"
|
||||
return dispatched[0]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pdf_attachment_sets_document_type(self, monkeypatch):
|
||||
"""A PDF attachment (application/pdf) must produce MessageType.DOCUMENT, not TEXT."""
|
||||
from gateway.platforms.base import MessageType
|
||||
|
||||
event = await self._dispatch_single_attachment(
|
||||
monkeypatch,
|
||||
content_type="application/pdf",
|
||||
att_id="6zLO3b-6Yf3zVWeLDctA.pdf",
|
||||
fetch_path="/tmp/report.pdf",
|
||||
fetch_ext=".pdf",
|
||||
)
|
||||
|
||||
assert event.message_type == MessageType.DOCUMENT, (
|
||||
f"Expected DOCUMENT, got {event.message_type}. "
|
||||
"PDFs must be classified as DOCUMENT so run.py injects file context."
|
||||
)
|
||||
assert "/tmp/report.pdf" in event.media_urls
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_text_plain_attachment_sets_document_type(self, monkeypatch):
|
||||
"""A text/plain attachment must produce MessageType.DOCUMENT, not TEXT."""
|
||||
from gateway.platforms.base import MessageType
|
||||
|
||||
event = await self._dispatch_single_attachment(
|
||||
monkeypatch,
|
||||
content_type="text/plain",
|
||||
att_id="notes.txt",
|
||||
fetch_path="/tmp/notes.txt",
|
||||
fetch_ext=".txt",
|
||||
)
|
||||
|
||||
assert event.message_type == MessageType.DOCUMENT, (
|
||||
f"Expected DOCUMENT, got {event.message_type}. "
|
||||
"text/plain must be classified as DOCUMENT so run.py injects file context."
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_text_html_attachment_sets_document_type(self, monkeypatch):
|
||||
"""A text/html attachment must produce MessageType.DOCUMENT (covers the text/* wildcard)."""
|
||||
from gateway.platforms.base import MessageType
|
||||
|
||||
event = await self._dispatch_single_attachment(
|
||||
monkeypatch,
|
||||
content_type="text/html",
|
||||
att_id="page.html",
|
||||
fetch_path="/tmp/page.html",
|
||||
fetch_ext=".html",
|
||||
)
|
||||
|
||||
assert event.message_type == MessageType.DOCUMENT, (
|
||||
f"Expected DOCUMENT, got {event.message_type}. "
|
||||
"text/html must be classified as DOCUMENT so run.py injects file context."
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# send_document now routes through _send_attachment (#5105 bonus)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue