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_USER_ID=@bot:matrix.org
|
||||||
MATRIX_PASSWORD=your_password_here
|
MATRIX_PASSWORD=your_password_here
|
||||||
MATRIX_PLATFORM_BACKEND=real
|
MATRIX_PLATFORM_BACKEND=real
|
||||||
|
MATRIX_AGENT_REGISTRY_PATH=config/matrix-agents.yaml
|
||||||
|
|
||||||
# Shared workspace contract
|
# Shared workspace contract
|
||||||
SURFACES_WORKSPACE_DIR=/workspace
|
SURFACES_WORKSPACE_DIR=/workspace
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ MATRIX_PASSWORD=... # или MATRIX_ACCESS_TOKEN=...
|
||||||
|
|
||||||
# Выбор backend: mock (по умолчанию) или real (подключение к platform-agent)
|
# Выбор backend: mock (по умолчанию) или real (подключение к platform-agent)
|
||||||
MATRIX_PLATFORM_BACKEND=real
|
MATRIX_PLATFORM_BACKEND=real
|
||||||
|
MATRIX_AGENT_REGISTRY_PATH=config/matrix-agents.yaml
|
||||||
|
|
||||||
# compose runtime: platform-agent service name + shared /workspace
|
# compose runtime: platform-agent service name + shared /workspace
|
||||||
AGENT_BASE_URL=http://platform-agent:8000
|
AGENT_BASE_URL=http://platform-agent:8000
|
||||||
|
|
@ -131,7 +132,13 @@ PROVIDER_URL=https://openrouter.ai/api/v1
|
||||||
PROVIDER_API_KEY=...
|
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.
|
Root `docker-compose.yml` теперь является основным локальным runtime для Matrix и platform-agent.
|
||||||
Он поднимает `matrix-bot`, `platform-agent` и общий volume `/workspace`.
|
Он поднимает `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",
|
"python-dotenv>=1.0",
|
||||||
"httpx>=0.27",
|
"httpx>=0.27",
|
||||||
"aiohttp>=3.9",
|
"aiohttp>=3.9",
|
||||||
|
"PyYAML>=6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[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