feat: add matrix routed platform facade
This commit is contained in:
parent
7627012f24
commit
242f4aadd3
3 changed files with 376 additions and 8 deletions
110
adapter/matrix/routed_platform.py
Normal file
110
adapter/matrix/routed_platform.py
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from collections.abc import AsyncIterator, Mapping
|
||||
|
||||
from adapter.matrix.store import get_room_meta
|
||||
from core.chat import ChatManager
|
||||
from core.store import StateStore
|
||||
from sdk.interface import (
|
||||
Attachment,
|
||||
MessageChunk,
|
||||
MessageResponse,
|
||||
PlatformClient,
|
||||
PlatformError,
|
||||
User,
|
||||
UserSettings,
|
||||
)
|
||||
|
||||
|
||||
class RoutedPlatformClient(PlatformClient):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
chat_mgr: ChatManager,
|
||||
store: StateStore,
|
||||
delegates: Mapping[str, PlatformClient],
|
||||
) -> None:
|
||||
if not delegates:
|
||||
raise ValueError("RoutedPlatformClient requires at least one delegate")
|
||||
self._chat_mgr = chat_mgr
|
||||
self._store = store
|
||||
self._delegates = dict(delegates)
|
||||
self._default_client = next(iter(self._delegates.values()))
|
||||
self._prototype_state = getattr(self._default_client, "_prototype_state", None)
|
||||
|
||||
async def get_or_create_user(
|
||||
self,
|
||||
external_id: str,
|
||||
platform: str,
|
||||
display_name: str | None = None,
|
||||
) -> User:
|
||||
return await self._default_client.get_or_create_user(
|
||||
external_id=external_id,
|
||||
platform=platform,
|
||||
display_name=display_name,
|
||||
)
|
||||
|
||||
async def send_message(
|
||||
self,
|
||||
user_id: str,
|
||||
chat_id: str,
|
||||
text: str,
|
||||
attachments: list[Attachment] | None = None,
|
||||
) -> MessageResponse:
|
||||
delegate, platform_chat_id = await self._resolve_delegate(user_id, chat_id)
|
||||
return await delegate.send_message(user_id, platform_chat_id, text, attachments)
|
||||
|
||||
async def stream_message(
|
||||
self,
|
||||
user_id: str,
|
||||
chat_id: str,
|
||||
text: str,
|
||||
attachments: list[Attachment] | None = None,
|
||||
) -> AsyncIterator[MessageChunk]:
|
||||
delegate, platform_chat_id = await self._resolve_delegate(user_id, chat_id)
|
||||
async for chunk in delegate.stream_message(user_id, platform_chat_id, text, attachments):
|
||||
yield chunk
|
||||
|
||||
async def get_settings(self, user_id: str) -> UserSettings:
|
||||
return await self._default_client.get_settings(user_id)
|
||||
|
||||
async def update_settings(self, user_id: str, action) -> None:
|
||||
await self._default_client.update_settings(user_id, action)
|
||||
|
||||
async def close(self) -> None:
|
||||
for delegate in self._delegates.values():
|
||||
close = getattr(delegate, "close", None)
|
||||
if callable(close):
|
||||
await close()
|
||||
|
||||
async def _resolve_delegate(self, user_id: str, local_chat_id: str) -> tuple[PlatformClient, str]:
|
||||
chat = await self._chat_mgr.get(local_chat_id, user_id)
|
||||
if chat is None:
|
||||
raise PlatformError(
|
||||
f"unknown matrix chat id: {local_chat_id}",
|
||||
code="MATRIX_CHAT_NOT_FOUND",
|
||||
)
|
||||
|
||||
room_meta = await get_room_meta(self._store, chat.surface_ref)
|
||||
if room_meta is None:
|
||||
raise PlatformError(
|
||||
f"matrix room is not bound: {chat.surface_ref}",
|
||||
code="MATRIX_ROOM_NOT_BOUND",
|
||||
)
|
||||
|
||||
agent_id = room_meta.get("agent_id")
|
||||
platform_chat_id = room_meta.get("platform_chat_id")
|
||||
if not agent_id or not platform_chat_id:
|
||||
raise PlatformError(
|
||||
f"matrix room routing is incomplete: {chat.surface_ref}",
|
||||
code="MATRIX_ROUTE_INCOMPLETE",
|
||||
)
|
||||
|
||||
delegate = self._delegates.get(str(agent_id))
|
||||
if delegate is None:
|
||||
raise PlatformError(
|
||||
f"unknown matrix agent id: {agent_id}",
|
||||
code="MATRIX_AGENT_NOT_FOUND",
|
||||
)
|
||||
|
||||
return delegate, str(platform_chat_id)
|
||||
Loading…
Add table
Add a link
Reference in a new issue