Users can now list available agents with !agent and select one by number. Selection persists in user metadata (selected_agent_id). If the current room has no agent binding yet, selecting an agent binds it immediately so the user can start messaging without !new. Also updates the dispatcher test to reflect that real-mode platform is now RoutedPlatformClient, not a bare RealPlatformClient.
175 lines
5 KiB
Python
175 lines
5 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from adapter.matrix.bot import build_runtime
|
|
from adapter.matrix.agent_registry import AgentDefinition, AgentRegistry
|
|
from adapter.matrix.handlers.agent import make_handle_agent
|
|
from adapter.matrix.store import get_room_meta, get_selected_agent_id, set_selected_agent_id, set_room_meta
|
|
from core.chat import ChatManager
|
|
from core.protocol import IncomingCommand, OutgoingMessage
|
|
from core.settings import SettingsManager
|
|
from core.store import InMemoryStore
|
|
from sdk.mock import MockPlatformClient
|
|
|
|
|
|
def _registry() -> AgentRegistry:
|
|
return AgentRegistry(
|
|
[
|
|
AgentDefinition(agent_id="agent-1", label="Analyst"),
|
|
AgentDefinition(agent_id="agent-2", label="Research"),
|
|
]
|
|
)
|
|
|
|
|
|
async def test_agent_command_lists_available_agents_with_selected_marker():
|
|
store = InMemoryStore()
|
|
await set_selected_agent_id(store, "@alice:example.org", "agent-2")
|
|
handler = make_handle_agent(store, _registry())
|
|
|
|
result = await handler(
|
|
event=IncomingCommand(
|
|
user_id="@alice:example.org",
|
|
platform="matrix",
|
|
chat_id="C1",
|
|
command="agent",
|
|
),
|
|
auth_mgr=None,
|
|
platform=MockPlatformClient(),
|
|
chat_mgr=ChatManager(None, store),
|
|
settings_mgr=SettingsManager(MockPlatformClient(), store),
|
|
)
|
|
|
|
assert result == [
|
|
OutgoingMessage(
|
|
chat_id="C1",
|
|
text=(
|
|
"Доступные агенты:\n"
|
|
"1. Analyst\n"
|
|
"2. Research [текущий]\n"
|
|
"\n"
|
|
"Выбери агент: !agent <номер>"
|
|
),
|
|
)
|
|
]
|
|
|
|
|
|
async def test_agent_command_persists_selected_agent_id():
|
|
store = InMemoryStore()
|
|
handler = make_handle_agent(store, _registry())
|
|
|
|
result = await handler(
|
|
event=IncomingCommand(
|
|
user_id="@alice:example.org",
|
|
platform="matrix",
|
|
chat_id="C1",
|
|
command="agent",
|
|
args=["2"],
|
|
),
|
|
auth_mgr=None,
|
|
platform=MockPlatformClient(),
|
|
chat_mgr=ChatManager(None, store),
|
|
settings_mgr=SettingsManager(MockPlatformClient(), store),
|
|
)
|
|
|
|
assert await get_selected_agent_id(store, "@alice:example.org") == "agent-2"
|
|
assert result == [
|
|
OutgoingMessage(
|
|
chat_id="C1",
|
|
text="Агент переключен на Research. Продолжай через !new.",
|
|
)
|
|
]
|
|
|
|
|
|
async def test_agent_command_binds_existing_unbound_room_to_selected_agent():
|
|
store = InMemoryStore()
|
|
chat_mgr = ChatManager(None, store)
|
|
await chat_mgr.get_or_create(
|
|
user_id="@alice:example.org",
|
|
chat_id="C1",
|
|
platform="matrix",
|
|
surface_ref="!room:example.org",
|
|
name="Research",
|
|
)
|
|
await set_room_meta(
|
|
store,
|
|
"!room:example.org",
|
|
{
|
|
"chat_id": "C1",
|
|
"matrix_user_id": "@alice:example.org",
|
|
"display_name": "Research",
|
|
},
|
|
)
|
|
handler = make_handle_agent(store, _registry())
|
|
|
|
result = await handler(
|
|
event=IncomingCommand(
|
|
user_id="@alice:example.org",
|
|
platform="matrix",
|
|
chat_id="C1",
|
|
command="agent",
|
|
args=["1"],
|
|
),
|
|
auth_mgr=None,
|
|
platform=MockPlatformClient(),
|
|
chat_mgr=chat_mgr,
|
|
settings_mgr=SettingsManager(MockPlatformClient(), store),
|
|
)
|
|
|
|
assert await get_selected_agent_id(store, "@alice:example.org") == "agent-1"
|
|
assert await get_room_meta(store, "!room:example.org") == {
|
|
"chat_id": "C1",
|
|
"matrix_user_id": "@alice:example.org",
|
|
"display_name": "Research",
|
|
"agent_id": "agent-1",
|
|
"platform_chat_id": "1",
|
|
}
|
|
assert result == [
|
|
OutgoingMessage(
|
|
chat_id="C1",
|
|
text="Агент Analyst выбран. Текущий чат готов к работе.",
|
|
)
|
|
]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_build_runtime_registers_agent_handler_when_registry_is_configured(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
tmp_path: Path,
|
|
):
|
|
registry_path = tmp_path / "matrix-agents.yaml"
|
|
registry_path.write_text(
|
|
"agents:\n"
|
|
" - id: agent-1\n"
|
|
" label: Analyst\n"
|
|
" - id: agent-2\n"
|
|
" label: Research\n",
|
|
encoding="utf-8",
|
|
)
|
|
monkeypatch.setenv("MATRIX_AGENT_REGISTRY_PATH", str(registry_path))
|
|
|
|
runtime = build_runtime(platform=MockPlatformClient())
|
|
|
|
result = await runtime.dispatcher.dispatch(
|
|
IncomingCommand(
|
|
user_id="@alice:example.org",
|
|
platform="matrix",
|
|
chat_id="C1",
|
|
command="agent",
|
|
)
|
|
)
|
|
|
|
assert result == [
|
|
OutgoingMessage(
|
|
chat_id="C1",
|
|
text=(
|
|
"Доступные агенты:\n"
|
|
"1. Analyst\n"
|
|
"2. Research\n"
|
|
"\n"
|
|
"Выбери агент: !agent <номер>"
|
|
),
|
|
)
|
|
]
|