feat: finalize matrix platform audit and docs

This commit is contained in:
Mikhail Putilovskij 2026-04-21 15:35:03 +03:00
parent 6422c7db58
commit 4524a6abc8
30 changed files with 3093 additions and 176 deletions

View file

@ -17,7 +17,6 @@ from adapter.matrix.handlers.settings import (
handle_help,
handle_settings,
handle_settings_connectors,
handle_unknown_command,
handle_settings_plan,
handle_settings_safety,
handle_settings_skills,
@ -25,6 +24,7 @@ from adapter.matrix.handlers.settings import (
handle_settings_status,
handle_settings_whoami,
handle_toggle_skill,
handle_unknown_command,
)
from core.handler import EventDispatcher
from core.protocol import IncomingCallback, IncomingCommand
@ -44,7 +44,13 @@ def register_matrix_handlers(
dispatcher.register(IncomingCommand, "archive", make_handle_archive(client, store))
dispatcher.register(IncomingCommand, "help", handle_help)
dispatcher.register(IncomingCommand, "settings", handle_settings)
dispatcher.register(IncomingCommand, "reset", make_handle_reset(store, prototype_state) if prototype_state is not None else handle_settings)
dispatcher.register(
IncomingCommand,
"reset",
make_handle_reset(store, prototype_state)
if prototype_state is not None
else handle_settings,
)
dispatcher.register(IncomingCommand, "settings_skills", handle_settings_skills)
dispatcher.register(IncomingCommand, "settings_connectors", handle_settings_connectors)
dispatcher.register(IncomingCommand, "settings_soul", handle_settings_soul)
@ -59,6 +65,10 @@ def register_matrix_handlers(
dispatcher.register(IncomingCommand, "*", handle_unknown_command)
if agent_api is not None and prototype_state is not None:
dispatcher.register(IncomingCommand, "save", make_handle_save(agent_api, store, prototype_state))
dispatcher.register(
IncomingCommand,
"save",
make_handle_save(agent_api, store, prototype_state),
)
dispatcher.register(IncomingCommand, "load", make_handle_load(store, prototype_state))
dispatcher.register(IncomingCommand, "context", make_handle_context(store, prototype_state))

View file

@ -1,14 +1,14 @@
from __future__ import annotations
import structlog
from typing import Any
import structlog
from nio.api import RoomVisibility
from nio.responses import RoomCreateError
from adapter.matrix.store import (
get_user_meta,
next_chat_id,
next_platform_chat_id,
set_room_meta,
set_user_meta,
)
@ -62,6 +62,7 @@ async def provision_workspace_chat(
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)
chat_resp = await client.room_create(
name=room_name,
@ -98,7 +99,7 @@ async def provision_workspace_chat(
"display_name": room_name,
"matrix_user_id": matrix_user_id,
"space_id": space_id,
"platform_chat_id": f"matrix:{chat_room_id}",
"platform_chat_id": platform_chat_id,
},
)
await chat_mgr.get_or_create(
@ -118,7 +119,15 @@ async def provision_workspace_chat(
}
async def handle_invite(client: Any, room: Any, event: Any, platform, store, auth_mgr, chat_mgr) -> None:
async def handle_invite(
client: Any,
room: Any,
event: Any,
platform,
store,
auth_mgr,
chat_mgr,
) -> None:
matrix_user_id = getattr(event, "sender", "")
display_name = getattr(room, "display_name", None) or matrix_user_id

View file

@ -1,12 +1,18 @@
from __future__ import annotations
from typing import Any, Awaitable, Callable
from collections.abc import Awaitable, Callable
from typing import Any
import structlog
from nio.api import RoomVisibility
from nio.responses import RoomCreateError
from adapter.matrix.store import get_user_meta, next_chat_id, set_room_meta
from adapter.matrix.store import (
get_user_meta,
next_chat_id,
next_platform_chat_id,
set_room_meta,
)
from core.protocol import IncomingCommand, OutgoingMessage
logger = structlog.get_logger(__name__)
@ -69,6 +75,7 @@ def make_handle_new_chat(
name = " ".join(event.args).strip() if event.args else ""
chat_id = await next_chat_id(store, event.user_id)
platform_chat_id = await next_platform_chat_id(store)
room_name = name or f"Чат {chat_id}"
response = await client.room_create(
@ -106,7 +113,7 @@ def make_handle_new_chat(
"display_name": room_name,
"matrix_user_id": event.user_id,
"space_id": space_id,
"platform_chat_id": f"matrix:{room_id}",
"platform_chat_id": platform_chat_id,
},
)
ctx = await chat_mgr.get_or_create(
@ -151,7 +158,10 @@ def make_handle_rename(
return [
OutgoingMessage(
chat_id=event.chat_id,
text="Этот чат не найден в локальном состоянии бота. Открой зарегистрированную комнату или создай новый чат через !new.",
text=(
"Этот чат не найден в локальном состоянии бота. "
"Открой зарегистрированную комнату или создай новый чат через !new."
),
)
]
@ -181,7 +191,10 @@ def make_handle_archive(
return [
OutgoingMessage(
chat_id=event.chat_id,
text="Этот чат не найден в локальном состоянии бота. Создай новый чат через !new.",
text=(
"Этот чат не найден в локальном состоянии бота. "
"Создай новый чат через !new."
),
)
]
ctx = await chat_mgr.get(event.chat_id, user_id=event.user_id)

View file

@ -7,7 +7,12 @@ from typing import TYPE_CHECKING
import httpx
import structlog
from adapter.matrix.store import get_room_meta, set_load_pending, set_platform_chat_id
from adapter.matrix.store import (
get_room_meta,
next_platform_chat_id,
set_load_pending,
set_platform_chat_id,
)
from core.protocol import IncomingCommand, OutgoingEvent, OutgoingMessage
if TYPE_CHECKING:
@ -45,7 +50,7 @@ async def _resolve_room_id(event: IncomingCommand, chat_mgr) -> str:
async def _resolve_context_scope(
event: IncomingCommand,
store: "StateStore",
store: StateStore,
chat_mgr,
) -> tuple[str, str | None]:
room_id = await _resolve_room_id(event, chat_mgr)
@ -54,7 +59,7 @@ async def _resolve_context_scope(
return room_id, platform_chat_id
def make_handle_save(agent_api, store: "StateStore", prototype_state: "PrototypeStateStore"):
def make_handle_save(agent_api, store: StateStore, prototype_state: PrototypeStateStore):
async def handle_save(
event: IncomingCommand, auth_mgr, platform, chat_mgr, settings_mgr
) -> list[OutgoingEvent]:
@ -96,7 +101,7 @@ def make_handle_save(agent_api, store: "StateStore", prototype_state: "Prototype
return handle_save
def make_handle_load(store: "StateStore", prototype_state: "PrototypeStateStore"):
def make_handle_load(store: StateStore, prototype_state: PrototypeStateStore):
async def handle_load(
event: IncomingCommand, auth_mgr, platform, chat_mgr, settings_mgr
) -> list[OutgoingEvent]:
@ -123,17 +128,15 @@ def make_handle_load(store: "StateStore", prototype_state: "PrototypeStateStore"
return handle_load
def make_handle_reset(store: "StateStore", prototype_state: "PrototypeStateStore"):
def make_handle_reset(store: StateStore, prototype_state: PrototypeStateStore):
async def handle_reset(
event: IncomingCommand, auth_mgr, platform, chat_mgr, settings_mgr
) -> list[OutgoingEvent]:
import time
room_id = await _resolve_room_id(event, chat_mgr)
room_meta = await get_room_meta(store, room_id)
old_chat_id = (room_meta or {}).get("platform_chat_id") or room_id
new_chat_id = f"matrix:{room_id}#{int(time.time())}"
new_chat_id = await next_platform_chat_id(store)
await set_platform_chat_id(store, room_id, new_chat_id)
disconnect = getattr(platform, "disconnect_chat", None)
@ -142,7 +145,12 @@ def make_handle_reset(store: "StateStore", prototype_state: "PrototypeStateStore
await prototype_state.clear_current_session(new_chat_id)
return [OutgoingMessage(chat_id=event.chat_id, text="Контекст сброшен. Агент не помнит предыдущий разговор.")]
return [
OutgoingMessage(
chat_id=event.chat_id,
text="Контекст сброшен. Агент не помнит предыдущий разговор.",
)
]
return handle_reset
@ -170,7 +178,7 @@ async def _call_reset_endpoint(agent_base_url: str, chat_id: str) -> list[Outgoi
return [OutgoingMessage(chat_id=chat_id, text="Контекст сброшен.")]
def make_handle_context(store: "StateStore", prototype_state: "PrototypeStateStore"):
def make_handle_context(store: StateStore, prototype_state: PrototypeStateStore):
async def handle_context(
event: IncomingCommand, auth_mgr, platform, chat_mgr, settings_mgr
) -> list[OutgoingEvent]:

View file

@ -2,7 +2,6 @@ from __future__ import annotations
from core.protocol import IncomingCommand, OutgoingMessage
HELP_TEXT = "\n".join(
[
"Команды",
@ -32,9 +31,7 @@ async def handle_settings(
return [OutgoingMessage(chat_id=event.chat_id, text=MVP_UNAVAILABLE_TEXT)]
async def handle_help(
event: IncomingCommand, auth_mgr, platform, chat_mgr, settings_mgr
) -> list:
async def handle_help(event: IncomingCommand, auth_mgr, platform, chat_mgr, settings_mgr) -> list:
return [OutgoingMessage(chat_id=event.chat_id, text=HELP_TEXT)]