from __future__ import annotations from typing import Any import structlog from nio.api import RoomVisibility from nio.responses import RoomCreateError from adapter.matrix.agent_registry import AgentRegistry from adapter.matrix.store import ( get_user_meta, next_platform_chat_id, set_room_meta, set_user_meta, ) logger = structlog.get_logger(__name__) def _default_room_name(chat_id: str) -> str: suffix = chat_id[1:] if chat_id.startswith("C") else chat_id return f"Чат {suffix}" async def provision_workspace_chat( client: Any, matrix_user_id: str, display_name: str, platform, store, auth_mgr, chat_mgr, room_name_override: str | None = None, registry: AgentRegistry | None = None, ) -> dict: user = await platform.get_or_create_user( external_id=matrix_user_id, platform="matrix", display_name=display_name, ) await auth_mgr.confirm(matrix_user_id) homeserver = matrix_user_id.split(":")[-1] user_meta = await get_user_meta(store, matrix_user_id) or {} space_id = user_meta.get("space_id") if not space_id: space_resp = await client.room_create( name=f"Lambda — {display_name}", space=True, visibility=RoomVisibility.private, invite=[matrix_user_id], ) if isinstance(space_resp, RoomCreateError): logger.error( "space creation failed", user=matrix_user_id, error=getattr(space_resp, "status_code", None), ) raise RuntimeError("Не удалось создать Space.") space_id = space_resp.room_id user_meta["space_id"] = space_id await set_user_meta(store, matrix_user_id, user_meta) next_chat_index = int(user_meta.get("next_chat_index", 1)) chat_id = f"C{next_chat_index}" platform_chat_id = await next_platform_chat_id(store) room_name = room_name_override or _default_room_name(chat_id) agent_id = None if registry is not None: agent_id = registry.get_agent_id_for_user(matrix_user_id) if agent_id is None and registry.agents: agent_id = registry.agents[0].agent_id chat_resp = await client.room_create( name=room_name, visibility=RoomVisibility.private, is_direct=False, invite=[matrix_user_id], ) if isinstance(chat_resp, RoomCreateError): logger.error( "chat room creation failed", user=matrix_user_id, error=getattr(chat_resp, "status_code", None), ) raise RuntimeError("Не удалось создать рабочий чат.") chat_room_id = chat_resp.room_id await client.room_put_state( room_id=space_id, event_type="m.space.child", content={"via": [homeserver]}, state_key=chat_room_id, ) user_meta["space_id"] = space_id user_meta["next_chat_index"] = next_chat_index + 1 await set_user_meta(store, matrix_user_id, user_meta) await set_room_meta( store, chat_room_id, { "room_type": "chat", "chat_id": chat_id, "display_name": room_name, "matrix_user_id": matrix_user_id, "space_id": space_id, "platform_chat_id": platform_chat_id, "agent_id": agent_id, }, ) await chat_mgr.get_or_create( user_id=matrix_user_id, chat_id=chat_id, platform="matrix", surface_ref=chat_room_id, name=room_name, ) return { "user": user, "space_id": space_id, "chat_room_id": chat_room_id, "chat_id": chat_id, "room_name": room_name, } async def handle_invite( client: Any, room: Any, event: Any, platform, store, auth_mgr, chat_mgr, registry: AgentRegistry | None = None, ) -> None: matrix_user_id = getattr(event, "sender", "") display_name = getattr(room, "display_name", None) or matrix_user_id await client.join(room.room_id) existing = await get_user_meta(store, matrix_user_id) if existing and existing.get("space_id"): return try: created = await provision_workspace_chat( client, matrix_user_id, display_name, platform, store, auth_mgr, chat_mgr, room_name_override="Чат 1", registry=registry, ) except RuntimeError as exc: logger.error("invite_workspace_provision_failed", user=matrix_user_id, error=str(exc)) return welcome = ( f"Привет, {created['user'].display_name or matrix_user_id}! Пиши — я здесь.\n\n" "Команды: !new · !chats · !rename · !archive · !clear · !help" ) await client.room_send( created["chat_room_id"], "m.room.message", {"msgtype": "m.text", "body": welcome}, )