From 655332000156a84b54b5294f89d6b1097f211a86 Mon Sep 17 00:00:00 2001 From: Mikhail Putilovskij Date: Mon, 27 Apr 2026 22:13:52 +0300 Subject: [PATCH] docs(05): capture phase context --- .../phases/05-mvp-deployment/05-CONTEXT.md | 130 ++++++++++++++++++ .../05-mvp-deployment/05-DISCUSSION-LOG.md | 65 +++++++++ 2 files changed, 195 insertions(+) create mode 100644 .planning/phases/05-mvp-deployment/05-CONTEXT.md create mode 100644 .planning/phases/05-mvp-deployment/05-DISCUSSION-LOG.md diff --git a/.planning/phases/05-mvp-deployment/05-CONTEXT.md b/.planning/phases/05-mvp-deployment/05-CONTEXT.md new file mode 100644 index 0000000..b0d2e81 --- /dev/null +++ b/.planning/phases/05-mvp-deployment/05-CONTEXT.md @@ -0,0 +1,130 @@ +# Phase 05: MVP Deployment — Context + +**Gathered:** 2026-04-27 +**Status:** Ready for planning + + +## 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 интеграция + + + + +## 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 + + + + +## 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 в стриме + + + + +## 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 + + + + +## 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/"]` — хост обеспечивает директорию + + + + +## 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 сигнал + + + +--- + +*Phase: 05-mvp-deployment* +*Context gathered: 2026-04-27* diff --git a/.planning/phases/05-mvp-deployment/05-DISCUSSION-LOG.md b/.planning/phases/05-mvp-deployment/05-DISCUSSION-LOG.md new file mode 100644 index 0000000..1e30b8c --- /dev/null +++ b/.planning/phases/05-mvp-deployment/05-DISCUSSION-LOG.md @@ -0,0 +1,65 @@ +# Phase 05: MVP Deployment — Discussion Log + +> **Audit trail only.** Do not use as input to planning, research, or execution agents. +> Decisions captured in CONTEXT.md — this log preserves the alternatives considered. + +**Date:** 2026-04-27 +**Phase:** 05-mvp-deployment +**Areas discussed:** !agent legacy, file transfer path, config format, docker-compose scope + +--- + +## !agent команда + +| Option | Description | Selected | +|--------|-------------|----------| +| Удалить | Убираем полностью — маппинг статический из конфига | ✓ | +| Оставить как no-op | Команда остаётся но ничего не делает | | +| Только для dev-режима | Работает когда нет user_agents в конфиге | | + +**User's choice:** Удалить +**Notes:** Команда была legacy от эпохи когда роутинг был динамическим. С user_agents в конфиге она не нужна. + +--- + +## Путь входящих файлов + +| Option | Description | Selected | +|--------|-------------|----------| +| incoming/{filename} | По docs/deploy-architecture.md — /agents/N/incoming/file | ✓ | +| surfaces/matrix/{user}/{room}/inbox/{file} | Текущий формат files.py | | + +**User's choice:** incoming/{filename} +**Notes:** Пользователь указал — это решение от платформенной команды, зафиксировано в docs/deploy-architecture.md. + +--- + +## Формат config/matrix-agents.yaml + +| Option | Description | Selected | +|--------|-------------|----------| +| Расширить текущий YAML | Добавить user_agents + base_url/workspace_path в тот же файл | ✓ | +| Отдельный prod-config.yaml | Два файла: registry (id/label) + prod конфиг (URL/user_agents) | | + +**User's choice:** Расширить текущий YAML +**Notes:** Один файл проще. Формат уже определён в docs/deploy-architecture.md. + +--- + +## docker-compose prod scope + +**User's choice:** docker-compose.prod.yml только для Matrix-бота +**Notes:** Платформа отвечает за агентские контейнеры — мы их не трогаем. Matrix-бот монтирует /agents/ как external host path, платформа обеспечивает содержимое. + +--- + +## Claude's Discretion + +- Обработка Matrix user_id не найденного в user_agents +- Имена env переменных для prod +- Формат .env.prod + +## Deferred Ideas + +- platform-master интеграция +- Per-chat chat_id isolation