diff --git a/adapter/matrix/handlers/__init__.py b/adapter/matrix/handlers/__init__.py index b2ea94d..a6b4a06 100644 --- a/adapter/matrix/handlers/__init__.py +++ b/adapter/matrix/handlers/__init__.py @@ -6,7 +6,7 @@ from adapter.matrix.handlers.chat import ( make_handle_new_chat, make_handle_rename, ) -from adapter.matrix.handlers.confirm import handle_cancel, handle_confirm +from adapter.matrix.handlers.confirm import make_handle_cancel, make_handle_confirm from adapter.matrix.handlers.settings import ( handle_settings, handle_settings_connectors, @@ -36,6 +36,6 @@ def register_matrix_handlers(dispatcher: EventDispatcher, client=None, store=Non dispatcher.register(IncomingCommand, "settings_status", handle_settings_status) dispatcher.register(IncomingCommand, "settings_whoami", handle_settings_whoami) - dispatcher.register(IncomingCallback, "confirm", handle_confirm) - dispatcher.register(IncomingCallback, "cancel", handle_cancel) + dispatcher.register(IncomingCallback, "confirm", make_handle_confirm(store)) + dispatcher.register(IncomingCallback, "cancel", make_handle_cancel(store)) dispatcher.register(IncomingCallback, "toggle_skill", handle_toggle_skill) diff --git a/adapter/matrix/handlers/confirm.py b/adapter/matrix/handlers/confirm.py index 20e12f2..4106cbc 100644 --- a/adapter/matrix/handlers/confirm.py +++ b/adapter/matrix/handlers/confirm.py @@ -1,19 +1,40 @@ from __future__ import annotations +from adapter.matrix.store import clear_pending_confirm, get_pending_confirm from core.protocol import IncomingCallback, OutgoingMessage -async def handle_confirm( - event: IncomingCallback, auth_mgr, platform, chat_mgr, settings_mgr -) -> list: - action_id = event.payload.get("action_id", "unknown") - return [ - OutgoingMessage(chat_id=event.chat_id, text=f"Действие подтверждено (id: {action_id}).") - ] +def make_handle_confirm(store=None): + async def handle_confirm( + event: IncomingCallback, auth_mgr, platform, chat_mgr, settings_mgr + ) -> list: + if store is None: + return [OutgoingMessage(chat_id=event.chat_id, text="Нет ожидающих подтверждений.")] + + pending = await get_pending_confirm(store, event.chat_id) + if not pending: + return [OutgoingMessage(chat_id=event.chat_id, text="Нет ожидающих подтверждений.")] + + description = pending.get("description", "действие") + await clear_pending_confirm(store, event.chat_id) + + return [OutgoingMessage(chat_id=event.chat_id, text=f"Подтверждено: {description}")] + + return handle_confirm -async def handle_cancel( - event: IncomingCallback, auth_mgr, platform, chat_mgr, settings_mgr -) -> list: - action_id = event.payload.get("action_id", "unknown") - return [OutgoingMessage(chat_id=event.chat_id, text=f"Действие отменено (id: {action_id}).")] +def make_handle_cancel(store=None): + async def handle_cancel( + event: IncomingCallback, auth_mgr, platform, chat_mgr, settings_mgr + ) -> list: + if store is None: + return [OutgoingMessage(chat_id=event.chat_id, text="Нет ожидающих подтверждений.")] + + pending = await get_pending_confirm(store, event.chat_id) + if not pending: + return [OutgoingMessage(chat_id=event.chat_id, text="Нет ожидающих подтверждений.")] + + await clear_pending_confirm(store, event.chat_id) + return [OutgoingMessage(chat_id=event.chat_id, text="Действие отменено.")] + + return handle_cancel diff --git a/adapter/matrix/handlers/settings.py b/adapter/matrix/handlers/settings.py index 51fb61e..a3e2172 100644 --- a/adapter/matrix/handlers/settings.py +++ b/adapter/matrix/handlers/settings.py @@ -22,21 +22,50 @@ def _parse_bool(value: str) -> bool: async def handle_settings( event: IncomingCommand, auth_mgr, platform, chat_mgr, settings_mgr ) -> list: - return [ - OutgoingMessage( - chat_id=event.chat_id, - text=( - "⚙️ Настройки Matrix\n" - "!skills\n" - "!connectors\n" - "!soul [field value]\n" - "!safety [trigger on|off]\n" - "!plan\n" - "!status\n" - "!whoami" - ), - ) - ] + settings = await settings_mgr.get(event.user_id) + chats = await chat_mgr.list_active(event.user_id) + + skills_lines = [] + for name, enabled in settings.skills.items(): + state = "on" if enabled else "off" + skills_lines.append(f" {state} {name}") + skills_text = "\n".join(skills_lines) if skills_lines else " нет навыков" + + soul_lines = [] + for key, value in (settings.soul or {}).items(): + soul_lines.append(f" {key}: {value}") + soul_text = "\n".join(soul_lines) if soul_lines else " по умолчанию" + + safety_lines = [] + for key, value in (settings.safety or {}).items(): + state = "on" if value else "off" + safety_lines.append(f" {state} {key}") + safety_text = "\n".join(safety_lines) if safety_lines else " по умолчанию" + + chat_lines = [f" {chat.display_name} ({chat.chat_id})" for chat in chats] + chats_text = "\n".join(chat_lines) if chat_lines else " нет активных чатов" + + dashboard = "\n".join( + [ + "Настройки", + "", + "Скиллы:", + skills_text, + "", + "Личность:", + soul_text, + "", + "Безопасность:", + safety_text, + "", + f"Активные чаты ({len(chats)}):", + chats_text, + "", + "Изменить: !skills, !soul, !safety", + ] + ) + + return [OutgoingMessage(chat_id=event.chat_id, text=dashboard)] async def handle_settings_skills( diff --git a/adapter/matrix/reactions.py b/adapter/matrix/reactions.py index 525a88d..fdfc237 100644 --- a/adapter/matrix/reactions.py +++ b/adapter/matrix/reactions.py @@ -1,9 +1,5 @@ from __future__ import annotations -from typing import Any - -from nio import AsyncClient - from sdk.interface import UserSettings CONFIRM_REACTION = "👍" @@ -13,56 +9,26 @@ REACTION_TO_INDEX = {emoji: idx + 1 for idx, emoji in enumerate(SKILL_REACTIONS) def build_skills_text(settings: UserSettings) -> str: - lines: list[str] = ["🧩 Скиллы"] + lines: list[str] = ["Скиллы"] for idx, (name, enabled) in enumerate(settings.skills.items(), start=1): - state = "✅" if enabled else "❌" + state = "on" if enabled else "off" emoji = SKILL_REACTIONS[idx - 1] if idx - 1 < len(SKILL_REACTIONS) else f"{idx}." - lines.append(f"{state} {emoji} {name}") + lines.append(f" {state} {emoji} {name}") lines.append("") - lines.append("Реакции 1️⃣-9️⃣ переключают навыки.") + lines.append("!skill on/off <название> — переключить навык.") return "\n".join(lines) def build_confirmation_text(description: str) -> str: return "\n".join( [ - "🤖 Lambda", + "Lambda", description, "", - f"{CONFIRM_REACTION} подтвердить · {CANCEL_REACTION} отменить", - "!yes — подтвердить · !no — отменить", + "Ответьте !yes для подтверждения или !no для отмены.", ] ) def reaction_to_skill_index(key: str) -> int | None: return REACTION_TO_INDEX.get(key) - - -async def add_reaction(client: AsyncClient, room_id: str, event_id: str, key: str) -> Any: - return await client.room_send( - room_id, - "m.reaction", - { - "m.relates_to": { - "rel_type": "m.annotation", - "event_id": event_id, - "key": key, - } - }, - ) - - -async def remove_reaction(client: AsyncClient, room_id: str, event_id: str, key: str) -> Any: - return await client.room_send( - room_id, - "m.reaction", - { - "m.relates_to": { - "rel_type": "m.annotation", - "event_id": event_id, - "key": key, - }, - "undo": True, - }, - )