feat(deploy): per-agent base_url and workspace_path routing

- AgentDefinition gains base_url and workspace_path fields (optional)
- load_agent_registry parses them from matrix-agents.yaml
- _build_platform_from_env uses agent.base_url per agent (falls back to AGENT_BASE_URL)
- _agent_workspace_root() resolves workspace per agent from registry
- _materialize_incoming_attachments saves files to agent workspace_path/incoming/
- send_outgoing accepts workspace_root param; reads outgoing files from agent workspace_path
- dispatch loop computes workspace_root from room agent_id and passes to _send_all
- config/matrix-agents.yaml and example updated with base_url and workspace_path
This commit is contained in:
Mikhail Putilovskij 2026-04-28 03:22:21 +03:00
parent d6b7720eca
commit 4bbae9affa
5 changed files with 108 additions and 21 deletions

View file

@ -1,7 +1,7 @@
from __future__ import annotations
from collections.abc import Mapping
from dataclasses import dataclass
from dataclasses import dataclass, field
from pathlib import Path
import yaml
@ -15,6 +15,8 @@ class AgentRegistryError(ValueError):
class AgentDefinition:
agent_id: str
label: str
base_url: str = field(default="")
workspace_path: str = field(default="")
class AgentRegistry:
@ -47,6 +49,15 @@ def _required_text(entry: Mapping[str, object], key: str) -> str:
return text
def _optional_text(entry: Mapping[str, object], key: str) -> str:
value = entry.get(key)
if value is None:
return ""
if not isinstance(value, str):
raise AgentRegistryError(f"agent entry field '{key}' must be a string")
return value.strip()
def _load_registry_data(path: str | Path) -> dict[str, object]:
try:
raw = yaml.safe_load(Path(path).read_text(encoding="utf-8"))
@ -72,10 +83,19 @@ def load_agent_registry(path: str | Path) -> AgentRegistry:
raise AgentRegistryError("each agent entry requires id and label")
agent_id = _required_text(entry, "id")
label = _required_text(entry, "label")
base_url = _optional_text(entry, "base_url")
workspace_path = _optional_text(entry, "workspace_path")
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))
agents.append(
AgentDefinition(
agent_id=agent_id,
label=label,
base_url=base_url,
workspace_path=workspace_path,
)
)
user_agents = raw.get("user_agents")
if user_agents is not None: