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:
parent
d6b7720eca
commit
4bbae9affa
5 changed files with 108 additions and 21 deletions
|
|
@ -146,10 +146,11 @@ def _build_platform_from_env(*, store: StateStore, chat_mgr: ChatManager) -> Pla
|
|||
prototype_state = PrototypeStateStore()
|
||||
registry = _load_agent_registry_from_env(required=True)
|
||||
assert registry is not None
|
||||
global_base_url = _agent_base_url_from_env()
|
||||
delegates = {
|
||||
agent.agent_id: RealPlatformClient(
|
||||
agent_id=agent.agent_id,
|
||||
agent_base_url=_agent_base_url_from_env(),
|
||||
agent_base_url=agent.base_url or global_base_url,
|
||||
prototype_state=prototype_state,
|
||||
platform="matrix",
|
||||
)
|
||||
|
|
@ -300,6 +301,8 @@ class MatrixBot:
|
|||
sender,
|
||||
incoming,
|
||||
)
|
||||
agent_id = (room_meta or {}).get("agent_id")
|
||||
workspace_root = self._agent_workspace_root(agent_id)
|
||||
try:
|
||||
outgoing = await self.runtime.dispatcher.dispatch(incoming)
|
||||
except PlatformError as exc:
|
||||
|
|
@ -319,7 +322,7 @@ class MatrixBot:
|
|||
else:
|
||||
if clear_staged_after_dispatch:
|
||||
await clear_staged_attachments(self.runtime.store, room.room_id, sender)
|
||||
await self._send_all(room.room_id, outgoing)
|
||||
await self._send_all(room.room_id, outgoing, workspace_root=workspace_root)
|
||||
|
||||
def _is_file_only_event(
|
||||
self, event: RoomMessage, incoming: IncomingMessage | IncomingCommand
|
||||
|
|
@ -439,13 +442,27 @@ class MatrixBot:
|
|||
True,
|
||||
)
|
||||
|
||||
def _agent_workspace_root(self, agent_id: str | None) -> Path:
|
||||
default = Path(os.environ.get("SURFACES_WORKSPACE_DIR", "/workspace"))
|
||||
if agent_id is None or self.runtime.registry is None:
|
||||
return default
|
||||
try:
|
||||
agent = self.runtime.registry.get(agent_id)
|
||||
if agent.workspace_path:
|
||||
return Path(agent.workspace_path)
|
||||
except Exception:
|
||||
pass
|
||||
return default
|
||||
|
||||
async def _materialize_incoming_attachments(
|
||||
self,
|
||||
room_id: str,
|
||||
matrix_user_id: str,
|
||||
incoming: IncomingMessage,
|
||||
) -> IncomingMessage:
|
||||
workspace_root = Path(os.environ.get("SURFACES_WORKSPACE_DIR", "/workspace"))
|
||||
room_meta = await get_room_meta(self.runtime.store, room_id)
|
||||
agent_id = (room_meta or {}).get("agent_id")
|
||||
workspace_root = self._agent_workspace_root(agent_id)
|
||||
materialized = []
|
||||
for attachment in incoming.attachments:
|
||||
materialized.append(
|
||||
|
|
@ -596,9 +613,20 @@ class MatrixBot:
|
|||
self.runtime.registry,
|
||||
)
|
||||
|
||||
async def _send_all(self, room_id: str, outgoing: list[OutgoingEvent]) -> None:
|
||||
async def _send_all(
|
||||
self,
|
||||
room_id: str,
|
||||
outgoing: list[OutgoingEvent],
|
||||
workspace_root: Path | None = None,
|
||||
) -> None:
|
||||
for event in outgoing:
|
||||
await send_outgoing(self.client, room_id, event, store=self.runtime.store)
|
||||
await send_outgoing(
|
||||
self.client,
|
||||
room_id,
|
||||
event,
|
||||
store=self.runtime.store,
|
||||
workspace_root=workspace_root,
|
||||
)
|
||||
|
||||
|
||||
async def prepare_live_sync(client: AsyncClient) -> str | None:
|
||||
|
|
@ -613,6 +641,7 @@ async def send_outgoing(
|
|||
room_id: str,
|
||||
event: OutgoingEvent,
|
||||
store: StateStore | None = None,
|
||||
workspace_root: Path | None = None,
|
||||
) -> None:
|
||||
if isinstance(event, OutgoingTyping):
|
||||
await client.room_typing(room_id, event.is_typing, timeout=25000)
|
||||
|
|
@ -627,7 +656,9 @@ async def send_outgoing(
|
|||
room_id, "m.room.message", {"msgtype": "m.text", "body": event.text}
|
||||
)
|
||||
if event.attachments:
|
||||
workspace_root = Path(os.environ.get("SURFACES_WORKSPACE_DIR", "/workspace"))
|
||||
workspace_root = workspace_root or Path(
|
||||
os.environ.get("SURFACES_WORKSPACE_DIR", "/workspace")
|
||||
)
|
||||
for attachment in event.attachments:
|
||||
if not attachment.workspace_path:
|
||||
continue
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue