Add Matrix agent registry loader
This commit is contained in:
parent
32b03becc8
commit
37f7ce27a2
6 changed files with 100 additions and 1 deletions
|
|
@ -6,6 +6,7 @@ MATRIX_HOMESERVER=https://matrix.org
|
|||
MATRIX_USER_ID=@bot:matrix.org
|
||||
MATRIX_PASSWORD=your_password_here
|
||||
MATRIX_PLATFORM_BACKEND=real
|
||||
MATRIX_AGENT_REGISTRY_PATH=config/matrix-agents.yaml
|
||||
|
||||
# Shared workspace contract
|
||||
SURFACES_WORKSPACE_DIR=/workspace
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ MATRIX_PASSWORD=... # или MATRIX_ACCESS_TOKEN=...
|
|||
|
||||
# Выбор backend: mock (по умолчанию) или real (подключение к platform-agent)
|
||||
MATRIX_PLATFORM_BACKEND=real
|
||||
MATRIX_AGENT_REGISTRY_PATH=config/matrix-agents.yaml
|
||||
|
||||
# compose runtime: platform-agent service name + shared /workspace
|
||||
AGENT_BASE_URL=http://platform-agent:8000
|
||||
|
|
@ -131,7 +132,13 @@ PROVIDER_URL=https://openrouter.ai/api/v1
|
|||
PROVIDER_API_KEY=...
|
||||
```
|
||||
|
||||
### 3. Compose runtime
|
||||
### 3. Registry агентов
|
||||
|
||||
1. Скопируй `config/matrix-agents.example.yaml` в `config/matrix-agents.yaml`
|
||||
2. Укажи `MATRIX_AGENT_REGISTRY_PATH=config/matrix-agents.yaml`
|
||||
3. Используй `!agent` в Matrix, чтобы выбрать активного upstream-агента
|
||||
|
||||
### 4. Compose runtime
|
||||
|
||||
Root `docker-compose.yml` теперь является основным локальным runtime для Matrix и platform-agent.
|
||||
Он поднимает `matrix-bot`, `platform-agent` и общий volume `/workspace`.
|
||||
|
|
|
|||
48
adapter/matrix/agent_registry.py
Normal file
48
adapter/matrix/agent_registry.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
class AgentRegistryError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AgentDefinition:
|
||||
agent_id: str
|
||||
label: str
|
||||
|
||||
|
||||
class AgentRegistry:
|
||||
def __init__(self, agents: list[AgentDefinition]) -> None:
|
||||
self.agents = agents
|
||||
self._by_id = {agent.agent_id: agent for agent in agents}
|
||||
|
||||
def get(self, agent_id: str) -> AgentDefinition:
|
||||
try:
|
||||
return self._by_id[agent_id]
|
||||
except KeyError as exc:
|
||||
raise AgentRegistryError(f"unknown agent id: {agent_id}") from exc
|
||||
|
||||
|
||||
def load_agent_registry(path: str | Path) -> AgentRegistry:
|
||||
raw = yaml.safe_load(Path(path).read_text(encoding="utf-8")) or {}
|
||||
entries = raw.get("agents")
|
||||
if not isinstance(entries, list) or not entries:
|
||||
raise AgentRegistryError("agents registry must contain a non-empty agents list")
|
||||
|
||||
agents: list[AgentDefinition] = []
|
||||
seen: set[str] = set()
|
||||
for entry in entries:
|
||||
agent_id = str(entry.get("id", "")).strip()
|
||||
label = str(entry.get("label", "")).strip()
|
||||
if not agent_id or not label:
|
||||
raise AgentRegistryError("each agent entry requires id and label")
|
||||
if agent_id in seen:
|
||||
raise AgentRegistryError(f"duplicate agent id: {agent_id}")
|
||||
seen.add(agent_id)
|
||||
agents.append(AgentDefinition(agent_id=agent_id, label=label))
|
||||
return AgentRegistry(agents)
|
||||
5
config/matrix-agents.example.yaml
Normal file
5
config/matrix-agents.example.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
agents:
|
||||
- id: agent-1
|
||||
label: Analyst
|
||||
- id: agent-2
|
||||
label: Research
|
||||
|
|
@ -16,6 +16,7 @@ dependencies = [
|
|||
"python-dotenv>=1.0",
|
||||
"httpx>=0.27",
|
||||
"aiohttp>=3.9",
|
||||
"PyYAML>=6.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
|
|
|||
37
tests/adapter/matrix/test_agent_registry.py
Normal file
37
tests/adapter/matrix/test_agent_registry.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from adapter.matrix.agent_registry import AgentRegistryError, load_agent_registry
|
||||
|
||||
|
||||
def test_load_agent_registry_reads_yaml_entries(tmp_path: Path):
|
||||
path = tmp_path / "agents.yaml"
|
||||
path.write_text(
|
||||
"agents:\n"
|
||||
" - id: agent-1\n"
|
||||
" label: Analyst\n"
|
||||
" - id: agent-2\n"
|
||||
" label: Research\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
registry = load_agent_registry(path)
|
||||
|
||||
assert [agent.agent_id for agent in registry.agents] == ["agent-1", "agent-2"]
|
||||
assert registry.get("agent-1").label == "Analyst"
|
||||
|
||||
|
||||
def test_load_agent_registry_rejects_duplicate_ids(tmp_path: Path):
|
||||
path = tmp_path / "agents.yaml"
|
||||
path.write_text(
|
||||
"agents:\n"
|
||||
" - id: agent-1\n"
|
||||
" label: Analyst\n"
|
||||
" - id: agent-1\n"
|
||||
" label: Duplicate\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with pytest.raises(AgentRegistryError, match="duplicate agent id"):
|
||||
load_agent_registry(path)
|
||||
Loading…
Add table
Add a link
Reference in a new issue