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

147 lines
11 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. Перейти на single-chat архитектуру (chat_id=0, один контекст на пользователя)
2. Упростить онбординг: DM-first без Space/rooms provisioning, welcome-сообщение при invite
3. Расширить config/matrix-agents.yaml — добавить user_agents (Matrix user_id → agent_id) и per-agent base_url/workspace_path
4. Обновить AgentRegistry и _build_platform_from_env для per-agent URL routing
5. Реализовать file transfer через shared volume /agents/: входящие → incoming/{filename}, исходящие через MsgEventSendFile
6. Добавить !clear (сброс контекста через переподключение AgentApi)
7. Написать docker-compose.prod.yml с полным стеком (matrix-bot + placeholder agent + named volume agents)
8. Удалить legacy: !agent, !new, !archive, !rename, !save, !load, Space-creation, C1/C2/C3 room provisioning
НЕ входит:
- Конфигурация агентских контейнеров (платформа)
- Telegram-адаптер
- E2EE
- platform-master интеграция
- !save / !load (ненадёжны без persistent memory в агенте)
</domain>
<decisions>
## Implementation Decisions
### Single-chat архитектура
- **D-01:** chat_id=0 для всех сообщений. Один контекст агента на пользователя. Изоляции между разными разговорами нет — вместо этого `!clear` сбрасывает контекст.
- **D-02:** Удалить всю multi-room инфраструктуру: C1/C2/C3, `!new`, `!archive`, `!rename`, Space-creation, room provisioning. Matrix-бот работает только в DM-комнате (личка с ботом).
- **D-03:** Удалить `!save` и `!load` — ненадёжны без persistent memory в агенте (MemorySaver сбрасывается на рестарте).
### Онбординг (DM-first)
- **D-04:** При получении invite в DM-комнату — принять, отправить welcome-сообщение: "Привет! Я Lambda AI-агент. Просто напиши — и я отвечу. `!clear` чтобы начать новый разговор, `!context` чтобы посмотреть статус."
- **D-05:** Никакого Space, никаких дочерних комнат. Вся переписка в одной DM-комнате.
### !clear (новая команда)
- **D-06:** Сбросить контекст агента — закрыть текущий AgentApi connection и создать новый (`await agent.close()` + `await agent.connect()`). Это сбрасывает MemorySaver. Подтвердить пользователю: "Контекст сброшен. Начнём с чистого листа."
### !agent команда
- **D-07:** Удалить полностью. Маппинг 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-бот + агент-контейнер (placeholder image `lambda-agent:latest` — уточнить у платформы) + named volume `agents`. Это позволяет тестировать полный стек самостоятельно. Платформа берёт отсюда схему интеграции для своего деплоя.
- **D-09:** Named volume `agents` монтируется в Matrix-бот как `/agents/` и в агент-контейнер как `/workspace`. 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*