feat: wire matrix runtime to real backend

This commit is contained in:
Mikhail Putilovskij 2026-04-08 01:40:38 +03:00
parent 9784ca6783
commit 94bdb44b93
3 changed files with 34 additions and 6 deletions

View file

@ -4,7 +4,7 @@
## Статус ## Статус
Прототип в разработке. SDK платформы ещё не готов — работаем через `MockPlatformClient`. Прототип в разработке. Matrix-адаптер по умолчанию работает через `MockPlatformClient`, но может переключаться на реальный direct-agent backend через `MATRIX_PLATFORM_BACKEND=real`.
| Поверхность | Статус | Описание | | Поверхность | Статус | Описание |
|---|---|---| |---|---|---|
@ -71,6 +71,8 @@ surfaces-bot/
- **Диалог** — сообщения, вложения, подтверждения `!yes` / `!no` и routing через `EventDispatcher` - **Диалог** — сообщения, вложения, подтверждения `!yes` / `!no` и routing через `EventDispatcher`
- **Стабильность** — перед `sync_forever()` бот делает bootstrap sync и стартует с `since`, чтобы не переигрывать старую timeline после рестарта - **Стабильность** — перед `sync_forever()` бот делает bootstrap sync и стартует с `since`, чтобы не переигрывать старую timeline после рестарта
- **Текущее ограничение** — encrypted DM пока не поддержан; ручное тестирование Matrix ведётся в незашифрованных комнатах и зависит от локального state-store бота - **Текущее ограничение** — encrypted DM пока не поддержан; ручное тестирование Matrix ведётся в незашифрованных комнатах и зависит от локального state-store бота
- **Backend selection**`MATRIX_PLATFORM_BACKEND=mock` остаётся значением по умолчанию; `MATRIX_PLATFORM_BACKEND=real` требует `AGENT_WS_URL=ws://host:port/agent_ws/`
- **Ограничения real backend** — пока это текстовый direct-agent прототип без вложений и без асинхронных callbacks; локальные настройки и user-state хранятся в `PrototypeStateStore`
--- ---
@ -89,7 +91,7 @@ class PlatformClient(Protocol):
Бот не управляет lifecycle контейнеров — это делает Master (платформа). Бот не управляет lifecycle контейнеров — это делает Master (платформа).
Бот передаёт `user_id` + `chat_id` + сообщение; платформа сама решает нужно ли поднять контейнер. Бот передаёт `user_id` + `chat_id` + сообщение; платформа сама решает нужно ли поднять контейнер.
Сейчас: `MockPlatformClient` в `sdk/mock.py`. Сейчас: `MockPlatformClient` в `sdk/mock.py`, а Matrix real backend собирается через `sdk/real.py` при `MATRIX_PLATFORM_BACKEND=real`.
Когда SDK готов: добавляем `SdkPlatformClient`, меняем одну строку в DI. Адаптеры и ядро не трогаем. Когда SDK готов: добавляем `SdkPlatformClient`, меняем одну строку в DI. Адаптеры и ядро не трогаем.
--- ---

View file

@ -35,7 +35,11 @@ from core.protocol import (
) )
from core.settings import SettingsManager from core.settings import SettingsManager
from core.store import InMemoryStore, SQLiteStore, StateStore from core.store import InMemoryStore, SQLiteStore, StateStore
from sdk.agent_session import AgentSessionClient, AgentSessionConfig
from sdk.interface import PlatformClient
from sdk.mock import MockPlatformClient from sdk.mock import MockPlatformClient
from sdk.prototype_state import PrototypeStateStore
from sdk.real import RealPlatformClient
logger = structlog.get_logger(__name__) logger = structlog.get_logger(__name__)
@ -44,7 +48,7 @@ load_dotenv(Path(__file__).resolve().parents[2] / ".env")
@dataclass @dataclass
class MatrixRuntime: class MatrixRuntime:
platform: MockPlatformClient platform: PlatformClient
store: StateStore store: StateStore
chat_mgr: ChatManager chat_mgr: ChatManager
auth_mgr: AuthManager auth_mgr: AuthManager
@ -52,7 +56,7 @@ class MatrixRuntime:
dispatcher: EventDispatcher dispatcher: EventDispatcher
def build_event_dispatcher(platform: MockPlatformClient, store: StateStore) -> EventDispatcher: def build_event_dispatcher(platform: PlatformClient, store: StateStore) -> EventDispatcher:
chat_mgr = ChatManager(platform, store) chat_mgr = ChatManager(platform, store)
auth_mgr = AuthManager(platform, store) auth_mgr = AuthManager(platform, store)
settings_mgr = SettingsManager(platform, store) settings_mgr = SettingsManager(platform, store)
@ -64,12 +68,24 @@ def build_event_dispatcher(platform: MockPlatformClient, store: StateStore) -> E
return dispatcher return dispatcher
def _build_platform_from_env() -> PlatformClient:
backend = os.environ.get("MATRIX_PLATFORM_BACKEND", "mock").strip().lower()
if backend == "real":
ws_url = os.environ["AGENT_WS_URL"]
return RealPlatformClient(
agent_sessions=AgentSessionClient(AgentSessionConfig(base_ws_url=ws_url)),
prototype_state=PrototypeStateStore(),
platform="matrix",
)
return MockPlatformClient()
def build_runtime( def build_runtime(
platform: MockPlatformClient | None = None, platform: PlatformClient | None = None,
store: StateStore | None = None, store: StateStore | None = None,
client: AsyncClient | None = None, client: AsyncClient | None = None,
) -> MatrixRuntime: ) -> MatrixRuntime:
platform = platform or MockPlatformClient() platform = platform or _build_platform_from_env()
store = store or InMemoryStore() store = store or InMemoryStore()
chat_mgr = ChatManager(platform, store) chat_mgr = ChatManager(platform, store)
auth_mgr = AuthManager(platform, store) auth_mgr = AuthManager(platform, store)

View file

@ -11,6 +11,7 @@ from adapter.matrix.handlers.auth import handle_invite
from adapter.matrix.store import get_room_meta, get_user_meta, set_user_meta from adapter.matrix.store import get_room_meta, get_user_meta, set_user_meta
from core.protocol import IncomingCallback, IncomingCommand, OutgoingMessage from core.protocol import IncomingCallback, IncomingCommand, OutgoingMessage
from sdk.mock import MockPlatformClient from sdk.mock import MockPlatformClient
from sdk.real import RealPlatformClient
async def test_matrix_dispatcher_registers_custom_handlers(): async def test_matrix_dispatcher_registers_custom_handlers():
@ -254,3 +255,12 @@ async def test_prepare_live_sync_returns_next_batch_from_bootstrap_sync():
client.sync.assert_awaited_once_with(timeout=0, full_state=True) client.sync.assert_awaited_once_with(timeout=0, full_state=True)
assert since == "s123" assert since == "s123"
async def test_build_runtime_uses_real_platform_when_matrix_backend_is_real(monkeypatch):
monkeypatch.setenv("MATRIX_PLATFORM_BACKEND", "real")
monkeypatch.setenv("AGENT_WS_URL", "ws://agent.example/agent_ws/")
runtime = build_runtime()
assert isinstance(runtime.platform, RealPlatformClient)