mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-12 08:51:53 +00:00
fix(gateway): classify email document attachments as DOCUMENT
Email cached document attachments and placed them in media_urls, but msg_type only flipped on image attachments — documents stayed TEXT and run.py's document-context injection (gated on MessageType.DOCUMENT) silently dropped them. Same bug class as Signal #12845. DOCUMENT wins over PHOTO for mixed attachments since image handling keys off per-path mime types while document injection gates strictly on message_type.
This commit is contained in:
parent
1e29ab38c7
commit
f03f161b39
2 changed files with 70 additions and 1 deletions
|
|
@ -470,8 +470,15 @@ class EmailAdapter(BasePlatformAdapter):
|
|||
for att in attachments:
|
||||
media_urls.append(att["path"])
|
||||
media_types.append(att["media_type"])
|
||||
if att["type"] == "image":
|
||||
if att["type"] == "image" and msg_type == MessageType.TEXT:
|
||||
msg_type = MessageType.PHOTO
|
||||
elif att["type"] == "document":
|
||||
# Document wins over PHOTO for mixed attachments: run.py's
|
||||
# image handling keys off the per-path image/* mime type
|
||||
# regardless of message_type, but document-context injection
|
||||
# gates strictly on MessageType.DOCUMENT — so DOCUMENT is the
|
||||
# only classification that surfaces both.
|
||||
msg_type = MessageType.DOCUMENT
|
||||
|
||||
# Store thread context for reply threading
|
||||
self._thread_context[sender_addr] = {
|
||||
|
|
|
|||
|
|
@ -393,6 +393,68 @@ class TestDispatchMessage(unittest.TestCase):
|
|||
self.assertEqual(captured_events[0].message_type, MessageType.PHOTO)
|
||||
self.assertEqual(captured_events[0].media_urls, ["/tmp/img.jpg"])
|
||||
|
||||
def test_document_attachment_sets_document_type(self):
|
||||
"""Email with a document attachment must set DOCUMENT so run.py injects file context."""
|
||||
import asyncio
|
||||
from gateway.platforms.base import MessageType
|
||||
adapter = self._make_adapter()
|
||||
captured_events = []
|
||||
|
||||
async def capture_handle(event):
|
||||
captured_events.append(event)
|
||||
|
||||
adapter.handle_message = capture_handle
|
||||
|
||||
msg_data = {
|
||||
"uid": b"6",
|
||||
"sender_addr": "user@test.com",
|
||||
"sender_name": "User",
|
||||
"subject": "Re: report",
|
||||
"message_id": "<msg6@test.com>",
|
||||
"in_reply_to": "",
|
||||
"body": "See attached",
|
||||
"attachments": [{"path": "/tmp/report.pdf", "filename": "report.pdf", "type": "document", "media_type": "application/pdf"}],
|
||||
"date": "",
|
||||
}
|
||||
|
||||
asyncio.run(adapter._dispatch_message(msg_data))
|
||||
self.assertEqual(len(captured_events), 1)
|
||||
self.assertEqual(captured_events[0].message_type, MessageType.DOCUMENT)
|
||||
self.assertEqual(captured_events[0].media_urls, ["/tmp/report.pdf"])
|
||||
|
||||
def test_mixed_image_and_document_prefers_document(self):
|
||||
"""DOCUMENT wins for mixed attachments — image handling keys off per-path
|
||||
mime types, but document injection gates strictly on MessageType.DOCUMENT."""
|
||||
import asyncio
|
||||
from gateway.platforms.base import MessageType
|
||||
adapter = self._make_adapter()
|
||||
captured_events = []
|
||||
|
||||
async def capture_handle(event):
|
||||
captured_events.append(event)
|
||||
|
||||
adapter.handle_message = capture_handle
|
||||
|
||||
msg_data = {
|
||||
"uid": b"7",
|
||||
"sender_addr": "user@test.com",
|
||||
"sender_name": "User",
|
||||
"subject": "Re: both",
|
||||
"message_id": "<msg7@test.com>",
|
||||
"in_reply_to": "",
|
||||
"body": "Photo and PDF",
|
||||
"attachments": [
|
||||
{"path": "/tmp/img.jpg", "filename": "img.jpg", "type": "image", "media_type": "image/jpeg"},
|
||||
{"path": "/tmp/report.pdf", "filename": "report.pdf", "type": "document", "media_type": "application/pdf"},
|
||||
],
|
||||
"date": "",
|
||||
}
|
||||
|
||||
asyncio.run(adapter._dispatch_message(msg_data))
|
||||
self.assertEqual(len(captured_events), 1)
|
||||
self.assertEqual(captured_events[0].message_type, MessageType.DOCUMENT)
|
||||
self.assertEqual(len(captured_events[0].media_urls), 2)
|
||||
|
||||
def test_source_built_correctly(self):
|
||||
"""Session source should have correct chat_id and user info."""
|
||||
import asyncio
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue