surfaces/.planning/phases/05-mvp-deployment/05-CONTEXT.md

130 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 05: MVP Deployment — Context
**Gathered:** 2026-04-27
**Status:** Ready for planning
<domain>
## Phase Boundary
Подготовить Matrix-бот к реальному деплою на lambda.coredump.ru:
1. Расширить config/matrix-agents.yaml — добавить user_agents (Matrix user_id → agent_id) и per-agent base_url/workspace_path
2. Обновить AgentRegistry и _build_platform_from_env для per-agent URL routing
3. Реализовать file transfer через shared volume /agents/: входящие файлы → incoming/{filename} в workspace агента, исходящие — читать из workspace и отправлять в Matrix
4. Написать docker-compose.prod.yml только для Matrix-бота (агентские контейнеры — зона платформы)
5. Удалить команду !agent (legacy от динамического роутинга)
НЕ входит:
- Конфигурация агентских контейнеров (платформа)
- Telegram-адаптер
- E2EE
- platform-master интеграция
</domain>
<decisions>
## Implementation Decisions
### !agent команда
- **D-01:** Удалить полностью. Маппинг user→agent теперь статический из config. Пользователь не может менять агента.
### Конфиг агентов (config/matrix-agents.yaml)
- **D-02:** Расширить текущий matrix-agents.yaml — добавить user_agents dict и поля base_url/workspace_path к каждому агенту. Один файл, один парсер. Формат по docs/deploy-architecture.md:
```yaml
user_agents:
"@user0:matrix.lambda.coredump.ru": agent-0
"@user1:matrix.lambda.coredump.ru": agent-1
agents:
- id: agent-0
label: "Agent 0"
base_url: "ws://lambda.coredump.ru:7000/agent_0/"
workspace_path: "/agents/0/"
```
- **D-03:** AgentDefinition расширяется полями base_url (str) и workspace_path (str). AgentRegistry добавляет user_agents dict (Matrix user_id → agent_id) и метод get_agent_id_by_user(matrix_user_id).
### Роутинг user → agent в _build_platform_from_env
- **D-04:** Вместо глобального AGENT_BASE_URL — per-agent URL из конфига. _build_platform_from_env строит delegates с правильным base_url для каждого агента. RoutedPlatformClient._resolve_delegate использует user_agents из registry для определения delegate по Matrix user_id.
### Входящие файлы (пользователь → агент)
- **D-05:** Путь внутри workspace агента: `incoming/{filename}`. Абсолютный путь: `{workspace_path}/incoming/{filename}` (например `/agents/0/incoming/photo.jpg`). Обновить files.py: `build_workspace_attachment_path` принимает workspace_path агента и строит путь `incoming/{filename}`. Передавать в agent.send_message() как attachments=["incoming/{filename}"] (относительно /workspace).
- **D-06:** workspace_path агента берётся из AgentDefinition по agent_id пользователя.
### Исходящие файлы (агент → пользователь)
- **D-07:** При получении MsgEventSendFile(path="output/report.pdf") — читать файл из `{workspace_path}/{path}`. Отправлять как Matrix file message. Обработчик в Matrix bot.py при обработке stream-ответов от агента.
### docker-compose для prod
- **D-08:** Отдельный docker-compose.prod.yml только для Matrix-бота. Монтирует /agents/ как host path volume (платформа обеспечивает сам volume на хосте). Env vars из .env.prod. Запуск: `docker compose -f docker-compose.prod.yml up`.
### Claude's Discretion
- Обработка случая когда Matrix user_id не найден в user_agents: вернуть ошибку пользователю или fallback на mock?
- Имя переменной окружения для пути к prod-конфигу (MATRIX_AGENT_REGISTRY_PATH уже существует — скорее всего оставить)
- Формат .env.prod
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### Deployment architecture (PRIMARY)
- `docs/deploy-architecture.md` — Топология, формат конфига, AgentApi lifecycle, file transfer protocol, открытые вопросы
### Существующий код (изменяем)
- `adapter/matrix/agent_registry.py` — AgentRegistry, AgentDefinition, load_agent_registry — расширяем
- `adapter/matrix/bot.py` — _build_platform_from_env, _load_agent_registry_from_env — обновляем роутинг
- `adapter/matrix/routed_platform.py` — RoutedPlatformClient._resolve_delegate — обновляем логику
- `adapter/matrix/files.py` — build_workspace_attachment_path, download_matrix_attachment — меняем путь
- `adapter/matrix/handlers/agent.py` — удаляем или делаем no-op (!agent handler)
- `config/matrix-agents.yaml` — расширяем формат
- `docker-compose.yml` — существующий dev compose (за основу для prod варианта)
### SDK (используем как есть)
- `sdk/real.py` — RealPlatformClient — base_url теперь per-instance, но сам класс не меняется
- `sdk/upstream_agent_api.py` — AgentApi, MsgEventSendFile — читаем MsgEventSendFile в стриме
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- `adapter/matrix/files.py::build_workspace_attachment_path` — уже строит путь к файлу, нужно заменить логику `surfaces/matrix/...` на `incoming/{filename}`
- `adapter/matrix/files.py::download_matrix_attachment` — скачивает файл, нужно передавать workspace_path агента
- `adapter/matrix/agent_registry.py::load_agent_registry` — парсер YAML, расширяем без переписывания
### Established Patterns
- `RoutedPlatformClient` + delegates: dict[agent_id, RealPlatformClient] — паттерн уже есть, нужно только per-agent URL при создании delegates
- `MATRIX_PLATFORM_BACKEND=real` активирует prod-path — сохраняем
- `MATRIX_AGENT_REGISTRY_PATH` — env var для пути к конфигу — сохраняем
### Integration Points
- `_build_platform_from_env` создаёт delegates — здесь меняется источник URL (из конфига, не из env)
- `RoutedPlatformClient._resolve_delegate` — здесь добавляется lookup по user_agents
- Matrix bot stream handler — здесь добавляется обработка MsgEventSendFile
</code_context>
<specifics>
## Specific Ideas
- AgentApi конструктор в master ветке: `AgentApi(agent_id, base_url, on_disconnect=..., chat_id=0)` — base_url это ws:// URL агента
- Входящий файл: bot скачивает из Matrix → пишет в `{workspace_path}/incoming/{filename}` → вызывает `agent.send_message(text, attachments=["incoming/{filename}"])` (путь relative to /workspace)
- Исходящий файл: при `MsgEventSendFile(path="output/report.pdf")` → читаем `{workspace_path}/output/report.pdf` → отправляем в Matrix через `client.upload()` → `client.room_send(m.file)`
- docker-compose.prod.yml монтирует volume: `volumes: ["/agents/:/agents/"]` — хост обеспечивает директорию
</specifics>
<deferred>
## Deferred Ideas
- platform-master интеграция (динамический get_agent_url через POST /api/v1/create) — когда feat/storage будет готов
- !agent как admin-override — не нужен для MVP, можно добавить позже если потребуется
- Per-chat context isolation через разные chat_id (сейчас chat_id=0 для всех) — ждём platform сигнал
</deferred>
---
*Phase: 05-mvp-deployment*
*Context gathered: 2026-04-27*