surfaces/core/handlers/message.py
Mikhail Putilovskij 76230392fa fix: normalize attachments to core Attachment type in message handler
Upstream AgentApi responses can return attachment objects that don't
implement the Attachment dataclass. _to_core_attachments coerces them
via duck-typing so OutgoingMessage always carries typed Attachment
instances regardless of the upstream response shape.
2026-04-23 14:56:00 +03:00

71 lines
2.3 KiB
Python

# core/handlers/message.py
from __future__ import annotations
from core.protocol import Attachment, IncomingMessage, OutgoingMessage, OutgoingTyping
def _infer_attachment_type(mime_type: str | None) -> str:
if not mime_type:
return "document"
if mime_type.startswith("image/"):
return "image"
if mime_type.startswith("audio/"):
return "audio"
if mime_type.startswith("video/"):
return "video"
return "document"
def _to_core_attachments(raw: list) -> list[Attachment]:
result = []
for a in raw:
if isinstance(a, Attachment):
result.append(a)
else:
result.append(Attachment(
type=getattr(a, "type", None) or _infer_attachment_type(getattr(a, "mime_type", None)),
url=getattr(a, "url", None),
filename=getattr(a, "filename", None),
mime_type=getattr(a, "mime_type", None),
workspace_path=getattr(a, "workspace_path", None),
))
return result
def _start_command(platform: str) -> str:
return "!start" if platform == "matrix" else "/start"
async def handle_message(event: IncomingMessage, auth_mgr, platform, chat_mgr, settings_mgr) -> list:
if not await auth_mgr.is_authenticated(event.user_id):
return [
OutgoingMessage(
chat_id=event.chat_id,
text=f"Введите {_start_command(event.platform)} чтобы начать.",
)
]
# Voice slot fallback: audio attachment without registered voice_handler
if event.attachments and event.attachments[0].type == "audio":
return [OutgoingMessage(
chat_id=event.chat_id,
text="Голосовые сообщения скоро поддержим.",
parse_mode="plain",
)]
response = await platform.send_message(
user_id=event.user_id,
chat_id=event.chat_id,
text=event.text,
attachments=event.attachments,
)
return [
OutgoingTyping(chat_id=event.chat_id, is_typing=False),
OutgoingMessage(
chat_id=event.chat_id,
text=response.response,
parse_mode="markdown",
attachments=_to_core_attachments(getattr(response, "attachments", [])),
),
]