From 4a2c2631cdab2318f12e3794ab51dab0ab486b8a Mon Sep 17 00:00:00 2001 From: Markov Date: Mon, 23 Feb 2026 16:15:40 +0100 Subject: [PATCH] =?UTF-8?q?docs:=20CONCEPTS.md=20v2=20=E2=80=94=20from=20d?= =?UTF-8?q?ocs=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONCEPTS.md | 897 +++++++++++++++++++++++++++++----------------------- 1 file changed, 495 insertions(+), 402 deletions(-) diff --git a/CONCEPTS.md b/CONCEPTS.md index 9cdcc0e..1d9c7b3 100644 --- a/CONCEPTS.md +++ b/CONCEPTS.md @@ -1,142 +1,223 @@ -# Team Board — Концепции системы (Source of Truth) +# Team Board — CONCEPTS.md v2 +**Единая точка правды** -**Версия:** 1.0 +**Версия:** 2.0 **Дата:** 2026-02-23 -**Статус:** Единая точка правды по всем концепциям Team Board +**Источник:** Только документация (не исходный код) +**Статус:** Source of Truth для всех концепций Team Board --- -## 1. Архитектура +## 1. Видение продукта -### 1.1 Общая схема +**Team Board** — платформа для управления AI-агентами, работающими как команда разработчиков над проектами. + +### Ключевые принципы + +**Человек — участник процесса, а не наблюдатель.** Всё происходит на человеческом языке, в прозрачном чате. Агенты не работают скрытно — они полноценные участники команды. + +**Агенты и люди равноправны.** Одна модель Member для всех участников. Агент может создавать задачи, назначать работу, ревьюить код, отклонять задачи с обоснованием. + +**Transparency First.** Все действия видны в чате проекта: создание задач, изменение статусов, MR события, коммуникация между агентами. + +**Специализация через роли.** Архитектор декомпозирует фичи на задачи, Кодер выполняет, Ревьюер проверяет. Каждый агент имеет свой промпт, модель и capabilities. + +### Что это НЕ + +- ❌ Не универсальный ассистент — команда специализированных агентов +- ❌ Не MetaGPT — человек участвует в процессе, не только наблюдает +- ❌ Не скрытое выполнение — всё прозрачно в чатах и задачах +- ❌ Не привязка к конкретному LLM — поддержка разных провайдеров + +--- + +## 2. Архитектура + +### 2.1 Общая схема ``` -┌─────────────┐ ┌──────────────┐ ┌──────────────┐ -│ Web Client │────▶│ BFF │────▶│ Tracker │ -│ (Next.js) │ │ (FastAPI) │ │ (FastAPI) │ -└─────────────┘ └──────────────┘ └──────┬───────┘ - │ - ┌────────────────────────────────────────┤ - │ │ │ │ - ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ ┌──▼───┐ - │Picogent │ │Picogent │ │Telegram │ │ DB │ - │ Кодер │ │Архитект │ │ Bridge │ │ Pg │ - └─────────┘ └─────────┘ └─────────┘ └──────┘ +┌─────────────────────────────────────────────────────────────┐ +│ FRONTEND (Next.js) │ +│ - Проекты, доски, задачи, чаты │ +│ - Authentik OAuth (запланировано) │ +└──────────────────────────┬──────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ BFF (Python/FastAPI) │ +│ - JWT авторизация │ +│ - Прокси к Tracker │ +└──────────────────────────┬──────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ TRACKER (Python/FastAPI) │ +│ - Ядро системы (внутренний сервис) │ +│ - REST API + WebSocket │ +│ - Роутинг событий │ +└──────────────────────────┬──────────────────────────────────┘ + │ + ┌─────────────────┼─────────────────┐ + ▼ ▼ ▼ +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ Picogent │ │ Picogent │ │ Telegram │ +│ Кодер │ │ Архитектор │ │ Bridge │ +│ (Node.js) │ │ (Node.js) │ │ (Node.js) │ +└─────────────┘ └─────────────┘ └─────────────┘ + │ │ │ + └─────────────────┼─────────────────┘ + ▼ + ┌─────────────┐ + │ PostgreSQL │ + │ + Redis │ + └─────────────┘ ``` -### 1.2 Компоненты и порты +### 2.2 Принципы архитектуры -| Компонент | Технологии | Порт | Доступность | Описание | -|-----------|------------|------|-------------|----------| -| **Tracker** | Python, FastAPI, SQLAlchemy, PostgreSQL | 8100 | Внутренняя | Ядро системы. REST API + WebSocket | +**Tracker-Centric:** Tracker — единственный источник правды. Всё остальное — клиенты. + +**Микросервисы:** Каждый компонент — независимый сервис. Агенты могут быть на разных серверах. + +**Event-Driven:** WebSocket для real-time событий, REST для мутаций. + +**Lazy Loading:** Агент при подключении НЕ грузит историю. Как человек — видит только новое. Если нужен контекст → использует read_messages(). + +### 2.3 Сервисы и порты + +| Сервис | Стек | Порт | Доступность | Описание | +|--------|------|------|-------------|----------| +| **Tracker** | Python, FastAPI, SQLAlchemy | 8100 | Внутренняя | Ядро: проекты, задачи, чаты, события | | **BFF** | Python, FastAPI | 8200 | Внешняя | Прокси для Web Client с JWT auth | | **Web Client** | Next.js 15, Tailwind CSS | 3100 | Внешняя | UI: канбан, чат, настройки | +| **Picogent** | Node.js, TypeScript, Pi Agent | — | Внутренняя | AI-агент процесс | +| **Telegram Bridge** | Node.js (запланировано) | — | Внутренняя | Дублирует чат в Telegram | | **PostgreSQL** | PostgreSQL 16 | 5433 | Внутренняя | База данных | | **Redis** | Redis 7 | 6380 | Внутренняя | Кеш (пока не используется) | -| **Picogent** | Node.js, TypeScript | — | Внутренняя | AI-агент процесс | -### 1.3 Протоколы взаимодействия +### 2.4 Принятые микросервисные паттерны -- **Web Client ↔ BFF:** HTTPS REST API + WebSocket (JWT auth) -- **BFF ↔ Tracker:** HTTP REST API + WebSocket (Token auth) -- **Агенты ↔ Tracker:** HTTP REST API + WebSocket (Token auth) -- **База данных:** PostgreSQL connection pool через SQLAlchemy +**✅ Saga Pattern:** Каждый шаг агента имеет компенсацию при сбое (task take → падение → task вернулся в todo). + +**✅ Idempotency:** Каждое событие имеет уникальный ID для предотвращения дублирования. + +**✅ Circuit Breaker:** Exponential backoff при недоступности Tracker. + +**✅ Centralized Logging:** Structured JSON logging (Pino для Node.js, structlog для Python). + +**❌ Redis Streams:** Отклонён как избыточный. WS для online + REST для reconnect достаточно. --- -## 2. Модели данных +## 3. Модели данных -### 2.1 Member (Участники) +### 3.1 Member (Участники) **Ключевой принцип:** Агенты и люди — единая модель. Различие только в `type` и методе авторизации. ```python Member: id: UUID (PK) - name: str # Отображаемое имя - slug: str (UNIQUE) # Уникальный идентификатор (a-z, 0-9, -) + name: str # "Кодер", "Eugene" + slug: str (UNIQUE) # "coder", "admin" (a-z, 0-9, -) type: str # "human" | "agent" role: str # "owner" | "member" | "observer" | "bridge" auth_method: str # "password" | "oauth" | "token" password_hash: str? # Для людей - token: str? (UNIQUE) # Для агентов/bridges + token: str? (UNIQUE) # Для агентов (tb-xxxxx) status: str # "online" | "offline" | "busy" avatar_url: str? created_at: timestamp updated_at: timestamp ``` -### 2.2 AgentConfig (Конфигурация агентов) +### 3.2 AgentConfig (Конфигурация агентов) + +Для `type=agent` — дополнительная конфигурация: ```python AgentConfig: id: UUID (PK) member_id: UUID (FK → Member, UNIQUE) capabilities: str[] # ["coding", "review", "testing"] - chat_listen: str # "all" | "mentions" - task_listen: str # "all" | "mentions" + chat_listen: str # "all" | "mentions" | "none" + task_listen: str # "all" | "assigned" | "none" prompt: str? # Системный промпт model: str? # LLM модель ``` -### 2.3 Project (Проекты) +**Listen Modes (раздельные):** +- **chat_listen** — фильтр сообщений в чатах +- **task_listen** — фильтр событий задач +- Примеры: Архитектор (all/all), Кодер (mentions/mentions), Тестер (mentions/all) + +### 3.3 Project (Проекты) ```python Project: id: UUID (PK) - name: str # Отображаемое название - slug: str (UNIQUE) # Уникальный ID (для URLs) + name: str # "Team Board" + slug: str (UNIQUE) # "team-board" description: str? # Описание (markdown) - repo_urls: str[] # Массив Git репозиториев + repo_urls: str[] # Multi-repo поддержка status: str # "active" | "archived" - task_counter: int # Счётчик для генерации номеров задач created_at: timestamp updated_at: timestamp ``` -### 2.4 Task (Задачи) +**Особенности:** +- **Multi-repo:** Проект может содержать несколько Git репозиториев +- **Документация:** Указывается в description или repo_urls, агенты читают при онбординге +- **Вкладки UI:** канбан, чат, дашборд, настройки, файлы, activity feed + +### 3.4 Task (Задачи) ```python Task: id: UUID (PK) project_id: UUID (FK → Project) - parent_id: UUID? (FK → Task) # Подзадача - number: int # Порядковый номер в проекте (1, 2, 3...) - title: str # Название задачи + parent_id: UUID? (FK → Task) # Подзадачи (бесконечная вложенность) + title: str # Название description: str? # Описание (markdown) type: str # "task" | "bug" | "epic" | "story" status: str # "backlog" | "todo" | "in_progress" | "in_review" | "done" priority: str # "critical" | "high" | "medium" | "low" - labels: str[] # Массив лейблов ["backend", "urgent"] - assignee_slug: str? # Кому назначена (Member.slug) - reviewer_slug: str? # Кто ревьюит (Member.slug) - watchers: str[] # Наблюдатели (массив Member.slug) + labels: str[] # ["backend", "urgent", "refactor"] + assignee_slug: str? (FK) # Кому назначена + reviewer_slug: str? (FK) # Кто ревьюит + watchers: str[] # Наблюдатели (Jira-паттерн) depends_on: UUID[] # Зависимости от других задач - position: int # Позиция в колонке канбана - time_spent: int # Потраченное время (минуты) + time_spent: int # Минуты (для аналитики) created_at: timestamp updated_at: timestamp ``` -**Связи:** -- Task.project → Project (многие к одному) -- Task.parent → Task (самоссылка для подзадач) -- Task.subtasks ← Task (обратная связь) +**Статусы:** Любой → любой переход разрешён (без жёсткого workflow). -### 2.5 Step (Шаги задачи) +**Подзадачи vs Этапы:** +- **Подзадачи** — полноценные Task на канбане (parent_id) +- **Этапы (Steps)** — чеклист внутри задачи (прогресс агента) + +**Watchers:** Автор задачи автоматически становится watcher. Любой может подписаться через MCP tools. + +**Агент может отклонить задачу** с обоснованием через `reject_task()`. + +### 3.5 Step (Этапы задачи) ```python Step: id: UUID (PK) task_id: UUID (FK → Task) - title: str # Описание шага + title: str # "Написать модели", "Создать тесты" done: bool # Выполнен ли position: int # Порядок в списке created_at: timestamp updated_at: timestamp ``` -### 2.6 Chat (Чаты) +**Назначение:** Live-прогресс работы агента. Агент сам создаёт этапы и отмечает выполненными. + +### 3.6 Chat (Чаты) ```python Chat: @@ -148,414 +229,396 @@ Chat: ``` **Типы чатов:** -- **Lobby** — глобальный чат (один на всю систему) -- **Project** — чат проекта (один на проект) +- **Lobby** — глобальный чат (один на инстанс) +- **Project Chat** — чат проекта (один на проект) +- **Task Comments** — НЕ отдельный чат, а Message с task_id -### 2.7 Message (Сообщения) +### 3.7 Message (Unified Message) -**Unified Message:** Одна модель для чат-сообщений И комментариев к задачам. +**Ключевое решение:** Одна модель для чат-сообщений И комментариев задач. ```python Message: id: UUID (PK) chat_id: UUID? (FK → Chat) # Если сообщение в чате task_id: UUID? (FK → Task) # Если комментарий к задаче - parent_id: UUID? (FK → Message) # Для threads в чатах + parent_id: UUID? (FK → Message) # Threads в чатах author_type: str # "human" | "agent" | "system" - author_slug: str # Member.slug автора - content: str # Текст сообщения (markdown) - mentions: str[] # @упоминания (массив Member.slug) - voice_url: str? # URL голосового сообщения + author_slug: str # Member.slug + content: str # Markdown текст + mentions: str[] # @упоминания (Member.slug) + voice_url: str? # Голосовое сообщение (Thoth) created_at: timestamp updated_at: timestamp ``` **Ограничения:** Ровно одно из `chat_id` или `task_id` должно быть заполнено. -### 2.8 Attachment (Вложения) +**Threads:** Только в чатах (parent_id). В задачах — просто лента комментариев. + +**Голосовые:** Thoth транскрибирует → content (текст) + voice_url (аудио). + +### 3.8 Attachment (Файлы) ```python Attachment: id: UUID (PK) message_id: UUID (FK → Message) - filename: str # Оригинальное имя файла - mime_type: str? # MIME тип - size: int # Размер в байтах - storage_path: str # Путь к файлу на диске + filename: str # Оригинальное имя + mime_type: str? + size: int # Байты + storage_path: str # Путь на диске created_at: timestamp ``` +**Файловая система:** Файлы = attachments к сообщениям (как в чате, так и в задачах). Отдельного файлового сервиса нет. + +**Документация проекта:** Ссылки в repo_urls или описании проекта. + --- -## 3. Авторизация +## 4. Авторизация -### 3.1 Типы авторизации +### 4.1 Типы авторизации -| Тип участника | Метод авторизации | Описание | -|---------------|-------------------|----------| +| Тип участника | Метод | Описание | +|---------------|-------|----------| | **human (Web UI)** | JWT Token | Логин/пароль → JWT | -| **human (MCP Client)** | JWT Token | Логин/пароль → JWT (будущее) | -| **agent** | Bearer Token | Статический токен в agent.json | +| **human (MCP Client)** | OAuth | login/password, OAuth (запланировано) | +| **agent (Picogent)** | Bearer Token | Статический токен в agent.json | | **bridge** | Bearer Token | Статический токен для мостов | -### 3.2 JWT Tokens (для людей) +### 4.2 JWT Tokens -- **Секрет:** `JWT_SECRET` (environment variable) - **Алгоритм:** HS256 -- **Payload:** `{"sub": member_id, "name": member_name, "exp": timestamp}` +- **Секрет:** JWT_SECRET (environment) +- **Payload:** `{sub: member_id, name: member_name, exp: timestamp}` - **Срок действия:** 30 дней (настраивается) -### 3.3 Agent Tokens +### 4.3 Agent Tokens -- **Формат:** `tb-` + random string (32 символа) -- **Хранение:** `Member.token` (уникальное поле) +- **Формат:** `tb-` + 32 случайных символа - **Генерация:** При создании агента через UI -- **Отзыв:** Через API `POST /api/v1/members/{slug}/revoke-token` +- **Хранение:** Member.token (уникальное поле) +- **Использование:** WebSocket auth + REST API (запланировано) -### 3.4 Роли и права +### 4.4 Роли и права -| Роль | Описание | Права | -|------|----------|-------| -| `owner` | Владелец инстанса | Все права | -| `member` | Обычный участник | `send_messages`, `create_tasks`, `update_tasks` | -| `observer` | Наблюдатель | Только чтение | -| `bridge` | Мост в другую систему | `send_messages` | +| Роль | Права | +|------|-------| +| `owner` | Все права | +| `member` | send_messages, create_tasks, update_tasks | +| `observer` | Только чтение | +| `bridge` | send_messages | -### 3.5 Процесс авторизации +**MCP Client:** Это человек с инструментами, НЕ агент. -**Web Client:** -1. POST /api/auth/login → JWT token -2. Сохранение в localStorage -3. Authorization: Bearer {jwt} в запросах -4. WebSocket: ?token={jwt} в query +### 4.5 Один токен на агента -**Agent:** -1. Статический токен из конфига -2. WS: `{"type": "auth", "token": "tb-xxx"}` -3. REST: Authorization: Bearer {token} (TODO: не реализовано) +Всё в одном контексте: задачи, чат, ответы. Агент видит полную картину, а не изолированные сессии. --- -## 4. WebSocket Protocol +## 5. WebSocket Protocol -### 4.1 Подключение +### 5.1 Принципы разделения -**URL:** `ws://localhost:8100/ws` (прямое) или `wss://dev.team.uix.su/agent-ws` (через nginx) +- **WebSocket** = real-time (события push + отправка сообщений в чат) +- **REST (MCP tools)** = все мутации: задачи, steps, файлы, статусы -### 4.2 Сообщения: Клиент → Сервер +### 5.2 URLs -| Тип | Формат | Описание | -|-----|--------|----------| -| `auth` | `{"type": "auth", "token": "..."}` | Авторизация | -| `heartbeat` | `{"type": "heartbeat", "status": "online"}` | Статус агента | -| `project.subscribe` | `{"type": "project.subscribe", "project_id": "uuid"}` | Подписка на проект | -| `project.unsubscribe` | `{"type": "project.unsubscribe", "project_id": "uuid"}` | Отписка | -| `chat.send` | `{"type": "chat.send", "chat_id": "uuid", "content": "text", "mentions": []}` | Сообщение в чат | -| `ack` | `{"type": "ack"}` | Подтверждение получения | +- **Прямой:** `ws://localhost:8100/ws` +- **Через nginx:** `wss://dev.team.uix.su/agent-ws` -### 4.3 Сообщения: Сервер → Клиент +### 5.3 Клиент → Сервер -| Тип | Описание | Данные | -|-----|----------|--------| -| `auth.ok` | Успешная авторизация | `{slug, lobby_chat_id, projects[], online[]}` | -| `auth.error` | Ошибка авторизации | `{message}` | -| `message.new` | Новое сообщение | `{id, chat_id, task_id, author_*, content, mentions, created_at}` | -| `agent.status` | Изменение статуса агента | `{slug, status}` | -| `task.created` | Создана задача | `{...TaskData}` (TODO: не реализовано) | -| `task.updated` | Обновлена задача | `{...TaskData}` (TODO: не реализовано) | -| `task.assigned` | Задача назначена | `{...TaskData}` (TODO: не реализовано) | +| Событие | Формат | +|---------|--------| +| `auth` | `{"type": "auth", "token": "tb-xxxxx"}` | +| `heartbeat` | `{"type": "heartbeat", "status": "online"}` | +| `project.subscribe` | `{"type": "project.subscribe", "project_id": "uuid"}` | +| `project.unsubscribe` | `{"type": "project.unsubscribe", "project_id": "uuid"}` | +| `chat.send` | `{"type": "chat.send", "chat_id": "uuid", "content": "text"}` | +| `ack` | `{"type": "ack"}` | -### 4.4 Фильтрация событий +### 5.4 Сервер → Клиент -События фильтруются на сервере по настройкам агента: +| Событие | Фильтрация | +|---------|-----------| +| `auth.ok` | — | +| `auth.error` | — | +| `message.new` | По chat_listen + task_listen + ownership | +| `task.created` | task_listen:all (запланировано) | +| `task.updated` | task_listen:all ИЛИ assignee/reviewer/watcher (запланировано) | +| `task.assigned` | Только assignee (запланировано) | +| `agent.status` | Всем | + +### 5.5 Фильтрация событий на сервере + +Агент получает только релевантные события: **message.new:** -- `chat_listen: "all"` — все сообщения в подписанных проектах -- `chat_listen: "mentions"` — только сообщения с @упоминанием +- chat_listen:all → все сообщения в подписанных проектах +- chat_listen:mentions → только @упоминания -**task.* (будущее):** -- `task_listen: "all"` — все события задач в подписанных проектах -- `task_listen: "mentions"` — только задачи где агент assignee/reviewer/watcher +**task events:** +- task_listen:all → все события задач +- task_listen:assigned → только assignee/reviewer/watchers + @mentions -### 4.5 Auth Flow +### 5.6 Project Subscribe = Chat + Task Events -``` -1. WebSocket Connect -2. Client → {"type": "auth", "token": "tb-xxx"} -3. Server validates token & creates session -4. Server → {"type": "auth.ok", "data": {...}} -5. Client → {"type": "project.subscribe", "project_id": "uuid"} (для каждого проекта) -6. Start heartbeat loop (каждые 30 секунд) -``` +Одна подписка на проект даёт события чата И задач (с фильтрацией по listen modes). -### 4.6 Heartbeat +### 5.7 Heartbeat и таймауты -- **Интервал:** Каждые 30 секунд -- **Timeout:** 90 секунд без heartbeat → `status=offline` -- **Формат:** `{"type": "heartbeat", "status": "online|busy|idle"}` -- **Реакция сервера:** Обновление `Member.status`, уведомление `agent.status` +- **Интервал:** 30 секунд +- **Timeout:** 90 секунд → status=offline +- **Уведомление:** agent.status в чат +- **Восстановление:** Незавершённые задачи → todo --- -## 5. REST API +## 6. REST API -**Base URL:** `http://localhost:8100/api/v1` (прямой) или `https://dev.team.uix.su/agent-api/api/v1` (через nginx) +### 6.1 Base URLs -### 5.1 Projects +- **Прямой:** `http://localhost:8100/api/v1` +- **Через nginx:** `https://dev.team.uix.su/agent-api/api/v1` -| Метод | Путь | Описание | Параметры | -|-------|------|----------|-----------| -| GET | `/projects` | Список проектов | — | -| GET | `/projects/{slug}` | Проект по slug | — | -| POST | `/projects` | Создать проект | `{name, slug, description?, repo_urls?}` | -| PATCH | `/projects/{slug}` | Обновить проект | `{name?, description?, repo_urls?, status?}` | -| DELETE | `/projects/{slug}` | Удалить проект | — | +### 6.2 Задачи -### 5.2 Tasks +| Method | Path | Описание | +|--------|------|----------| +| GET | `/tasks` | Список (фильтры: project_id, status, assignee, labels) | +| GET | `/tasks/{id}` | По ID | +| POST | `/tasks?project_slug=X` | Создать | +| PATCH | `/tasks/{id}` | Обновить поля | +| DELETE | `/tasks/{id}` | Удалить | +| POST | `/tasks/{id}/take?slug=X` | Взять (атомарно, 409 если занята) | +| POST | `/tasks/{id}/reject` | Отклонить `{slug, reason}` | +| POST | `/tasks/{id}/assign` | Назначить `{assignee_slug}` | +| POST | `/tasks/{id}/watch?slug=X` | Подписаться | +| DELETE | `/tasks/{id}/watch?slug=X` | Отписаться | -| Метод | Путь | Описание | Параметры | -|-------|------|----------|-----------| -| GET | `/tasks` | Список задач | `?project_id=X&status=Y&assignee=Z&label=W` | -| GET | `/tasks/{id}` | Задача по ID | — | -| POST | `/tasks?project_slug=X` | Создать задачу | `{title, description?, type?, status?, priority?, labels?, parent_id?, assignee_slug?, depends_on?}` | -| PATCH | `/tasks/{id}` | Обновить задачу | `{title?, description?, type?, status?, priority?, labels?, assignee_slug?, reviewer_slug?, position?}` | -| DELETE | `/tasks/{id}` | Удалить задачу | — | +### 6.3 Steps -**Специальные операции с задачами:** +| Method | Path | Описание | +|--------|------|----------| +| GET | `/tasks/{id}/steps` | Список | +| POST | `/tasks/{id}/steps` | Создать `{title}` | +| PATCH | `/tasks/{tid}/steps/{sid}` | Обновить `{done: true}` | +| DELETE | `/tasks/{tid}/steps/{sid}` | Удалить | -| Метод | Путь | Описание | Параметры | -|-------|------|----------|-----------| -| POST | `/tasks/{id}/take?slug=X` | Взять задачу (атомарно) | — | -| POST | `/tasks/{id}/reject` | Отклонить задачу | `{reason}` | -| POST | `/tasks/{id}/assign` | Назначить задачу | `{assignee_slug}` | -| POST | `/tasks/{id}/watch?slug=X` | Подписаться на задачу | — | -| DELETE | `/tasks/{id}/watch?slug=X` | Отписаться от задачи | — | +### 6.4 Messages (Unified) -### 5.3 Steps - -| Метод | Путь | Описание | Параметры | -|-------|------|----------|-----------| -| GET | `/tasks/{id}/steps` | Список шагов | — | -| POST | `/tasks/{id}/steps` | Создать шаг | `{title}` | -| PATCH | `/tasks/{tid}/steps/{sid}` | Обновить шаг | `{title?, done?}` | -| DELETE | `/tasks/{tid}/steps/{sid}` | Удалить шаг | — | - -### 5.4 Messages (Unified) - -| Метод | Путь | Описание | Параметры | -|-------|------|----------|-----------| -| GET | `/messages` | Список сообщений | `?chat_id=X&task_id=Y&limit=50&offset=0` | -| POST | `/messages` | Отправить сообщение | `{chat_id?, task_id?, content, author_type?, author_slug?, mentions?}` | -| GET | `/messages/{id}/replies` | Треды сообщения | — | - -### 5.5 Members - -| Метод | Путь | Описание | Параметры | -|-------|------|----------|-----------| -| GET | `/members` | Список участников | — | -| GET | `/members/{slug}` | Участник по slug | — | -| POST | `/members` | Создать участника | `{name, slug, type?, agent_config?}` | -| PATCH | `/members/{slug}` | Обновить участника | `{name?, role?, status?, agent_config?}` | -| POST | `/members/{slug}/regenerate-token` | Перегенерировать токен | — | -| POST | `/members/{slug}/revoke-token` | Отозвать токен | — | - -### 5.6 Attachments (TODO) - -| Метод | Путь | Описание | Статус | -|-------|------|----------|--------| -| POST | `/messages/{id}/attachments` | Загрузить файл | **TODO** | -| GET | `/attachments/{id}` | Скачать файл | **TODO** | -| GET | `/attachments?task_id=X` | Файлы задачи | **TODO** | - ---- - -## 6. Агенты - -### 6.1 Концепция - -- **Один процесс = один агент** (picogent) -- **Одна сессия на агента** — видит всё: задачи, чат, ответы -- **Роль = конфигурация** в agent.json - -### 6.2 Конфигурация агента (agent.json) +| Method | Path | Описание | +|--------|------|----------| +| GET | `/messages?chat_id=X&limit=50` | Сообщения чата | +| GET | `/messages?task_id=X` | Комментарии задачи | +| POST | `/messages` | Отправить | +| GET | `/messages/{id}/replies` | Тред | +**Send message format:** ```json { - "name": "Кодер", - "slug": "coder", - "prompt": "Ты опытный разработчик...", - "model": "sonnet", - "capabilities": ["coding", "review"], - "chat_listen": "mentions", - "task_listen": "mentions", - "tracker_url": "http://localhost:8100", - "token": "tb-agent-xxx" + "chat_id": "uuid (или null)", + "task_id": "uuid (или null)", + "content": "text", + "author_type": "agent", + "author_slug": "coder", + "mentions": [] } ``` -### 6.3 Режимы прослушивания +### 6.5 Projects & Members -**Chat Listen:** -- `all` — получает все сообщения в подписанных проектах -- `mentions` — только при @упоминании +| Resource | Methods | Описание | +|----------|---------|----------| +| `/projects` | GET, POST, PATCH, DELETE | CRUD проектов | +| `/members` | GET, POST, PATCH | CRUD участников | -**Task Listen:** -- `all` — получает все события задач в подписанных проектах -- `mentions` — только задачи где агент assignee/reviewer/watcher +### 6.6 Attachments (запланировано) -### 6.4 Capabilities (способности) - -Массив строк, описывающих что умеет агент: -- `"coding"` — написание кода -- `"review"` — ревью кода -- `"testing"` — тестирование -- `"documentation"` — документация -- `"architecture"` — архитектурные решения - -### 6.5 Жизненный цикл агента - -1. **Запуск:** Читает agent.json, подключается к Tracker -2. **Auth:** Отправляет токен, получает контекст -3. **Subscribe:** Подписывается на нужные проекты -4. **Listen:** Получает события по WebSocket -5. **Action:** Выполняет действия через REST API -6. **Heartbeat:** Каждые 30 секунд сообщает о статусе -7. **Disconnect:** При отключении статус → offline - -### 6.6 Checkpoint Pattern - -**Проблема:** LLM блокирующий — агент не может получать события во время обдумывания. - -**Решение:** -- Короткие задачи (5-10 минут) -- Проверка входящих событий между шагами -- Уведомления о статусе `busy` во время работы +| Method | Path | Статус | +|--------|------|--------| +| POST | `/messages/{id}/attachments` | TODO | +| GET | `/attachments/{id}` | TODO | +| GET | `/attachments?task_id=X` | TODO | --- -## 7. BFF (Backend for Frontend) +## 7. Агенты -### 7.1 Роль BFF +### 7.1 Философия агентов -- **Прокси** между Web Client и Tracker -- **Авторизация** пользователей (JWT) -- **WebSocket прокси** с токен-аутентификацией -- **Трансформация данных** (при необходимости) +**Агент = чёрный ящик.** Tracker не знает что внутри — LLM, скрипт или человек. Может быть написан на любом языке. -### 7.2 Технологии +**Единый контекст:** Одна сессия на агента. Видит всё: задачи, чат, ответы. НЕ создавать отдельные сессии на задачу. + +**Checkpoint Pattern:** LLM блокирующий → короткие задачи (5-10 мин) + проверка входящих между шагами. + +### 7.2 Capabilities (способности) + +Массив строк, описывающий что умеет агент: +- `"coding"` — написание кода +- `"review"` — код-ревью +- `"testing"` — тестирование +- `"architecture"` — архитектурные решения +- `"documentation"` — документация + +**Label matching:** Задача с лейблом "coding" → только агенты с capability "coding". + +### 7.3 Listen Modes + +**chat_listen:** +- `all` — все сообщения в подписанных проектах +- `mentions` — только @упоминания +- `none` — не получает + +**task_listen:** +- `all` — все task-события +- `assigned` — только свои (assignee/reviewer/watcher) + @mentions +- `none` — не получает + +### 7.4 Router (в Picogent) + +**Принцип:** Максимум разговорной речи. Все события → текстовые сообщения → единственная сессия агента. + +``` +WS event → Router: + task.assigned → "Тебе назначена задача TB-42: ..." → runAgent(текст) + chat.message → "[чат] @author: ..." → runAgent(текст) + task.comment → "[комментарий TB-42] @author: ..." → runAgent(текст) + task.taken → internal: убрать из available (НЕ в промпт) +``` + +Агент сам решает что делать через MCP tools. + +### 7.5 Pi Agent Core + +**Picogent** использует Pi Agent Core — in-process agent loop: +- Dual transport: HTTP + WebSocket +- Skills, sessions, sandbox, directory mode +- Заменяет runner/ — более зрелая реализация + +### 7.6 Agent Home (запланировано) + +``` +agents/coder/ + agent.json # конфиг + prompt.md # само-улучшаемый промпт + memory/ # per-project память + workspace/ # рабочие файлы + sessions/ # сессии (JSONL) +``` + +--- + +## 8. BFF (Backend for Frontend) + +### 8.1 Роль + +- **Единственный внешний endpoint** — Tracker недоступен извне +- **JWT авторизация** для людей +- **WebSocket прокси** с токен-валидацией +- **CORS** для фронтенда + +### 8.2 Технологии - Python, FastAPI -- JWT авторизация -- HTTP Client (httpx) -- WebSocket прокси +- JWT middleware +- WebSocket proxy +- HTTP client (httpx) -### 7.3 Конфигурация (environment) +### 8.3 Прокси логика + +**REST:** +1. Клиент → BFF (JWT validation) +2. BFF → Tracker (с TRACKER_TOKEN) +3. Добавление author_slug в сообщения +4. Ответ клиенту + +**WebSocket:** +1. Client → `wss://bff/ws?token={jwt}` +2. BFF валидирует JWT +3. BFF → `ws://tracker/ws` с TRACKER_TOKEN +4. Двусторонний relay + +### 8.4 Конфигурация ```bash -# Tracker TRACKER_URL=http://localhost:8100 TRACKER_WS_URL=ws://localhost:8100/ws TRACKER_TOKEN=tb-admin-xxx - -# Auth JWT_SECRET=secret-key AUTH_USER=admin AUTH_PASS=password - -# Server -BFF_HOST=0.0.0.0 -BFF_PORT=8200 ``` -### 7.4 WebSocket прокси - -1. **Client подключение:** `wss://dev.team.uix.su/ws?token={jwt}` -2. **Валидация JWT:** Проверка токена, извлечение user -3. **Tracker подключение:** `ws://localhost:8100/ws` с TRACKER_TOKEN -4. **Двусторонний relay:** Client ↔ BFF ↔ Tracker - -### 7.5 REST прокси - -Все API запросы проксируются с добавлением: -- **Авторизация:** Проверка JWT -- **Трансформация:** Добавление `author_slug` в сообщения -- **Логирование:** Запросы и ответы -- **CORS:** Для фронтенда - --- -## 8. Фронтенд (Web Client) +## 9. Фронтенд -### 8.1 Технологии +### 9.1 Технологии -- **Framework:** Next.js 15 (App Router) -- **Styling:** Tailwind CSS -- **State:** React hooks (useState, useEffect) -- **HTTP:** fetch API -- **WebSocket:** Native WebSocket API +- **Next.js 15** (App Router) +- **Tailwind CSS** для стилизации +- **Native WebSocket API** +- **TypeScript** типизация -### 8.2 Структура страниц - -- `/login` — Авторизация -- `/` — Список проектов -- `/projects/[slug]` — Канбан доска проекта -- `/projects/[slug]/settings` — Настройки проекта (TODO) -- `/agents` — Управление агентами (TODO) - -### 8.3 Компоненты +### 9.2 Реализованные компоненты | Компонент | Описание | Статус | |-----------|----------|--------| -| `KanbanBoard` | Drag & drop доска + mobile tabs | ✅ Реализован | -| `TaskModal` | Модалка задачи (title, description, assignee, delete) | ✅ Базовая версия | -| `ChatPanel` | Чат (lobby) | ✅ Базовая версия | -| `CreateTaskModal` | Создание задачи | ✅ Реализован | -| `CreateProjectModal` | Создание проекта | ✅ Реализован | -| `AuthGuard` | Проверка авторизации | ✅ Реализован | +| `KanbanBoard` | Drag & drop + mobile tabs | ✅ Работает | +| `TaskModal` | title, description, status, priority, assignee | ✅ Базовая версия | +| `ChatPanel` | Lobby чат | ✅ Работает | +| `CreateTaskModal` | Создание задачи | ✅ Работает | +| `CreateProjectModal` | Создание проекта | ✅ Работает | +| `AuthGuard` | Проверка авторизации | ✅ Работает | -### 8.4 API клиент (api.ts) +### 9.3 Планируемые компоненты -- **Base URL:** `process.env.NEXT_PUBLIC_API_URL` -- **Авторизация:** JWT из localStorage -- **Обработка ошибок:** 401 → редирект на /login -- **TypeScript типы** для всех моделей +- **TaskModal улучшения:** комментарии, steps, watchers +- **Agent Management:** страница /agents с генерацией токенов +- **Dashboard:** метрики и activity feed проекта +- **Mobile UI:** адаптация под телефоны -### 8.5 WebSocket клиент (ws.ts) +### 9.4 API клиент + +- **Base URL:** process.env.NEXT_PUBLIC_API_URL +- **Auth:** JWT из localStorage +- **Error handling:** 401 → redirect /login +- **TypeScript types** для всех моделей + +### 9.5 WebSocket клиент ```typescript class WSClient { - // Подключение через BFF с JWT токеном - connect() // ws://bff/ws?token=jwt - - // Event handlers + connect(jwt: string) // ws://bff/ws?token=jwt on(type: string, handler: Function) - - // Convenience methods subscribeProject(projectId: string) sendChat(chatId: string, content: string) - sendTaskComment(taskId: string, content: string) heartbeat(status: string) } ``` -### 8.6 Состояние приложения - -- **Авторизация:** JWT в localStorage -- **Проекты:** Загружаются при входе в систему -- **Задачи:** Загружаются для каждого проекта -- **WebSocket:** Глобальный клиент, подписка по проектам -- **Real-time:** Обновления через WebSocket события - --- -## 9. Деплой +## 10. Деплой -### 9.1 Docker Compose (разработка) +### 10.1 Окружения + +- **dev.team.uix.su** — активное окружение +- **team.uix.su** — placeholder для продакшена + +### 10.2 Docker Compose (разработка) ```yaml services: tracker: - build: ./tracker + build: ./services/tracker ports: ["8100:8100"] depends_on: [postgres, redis] @@ -563,18 +626,19 @@ services: image: postgres:16-alpine ports: ["5433:5432"] - redis: - image: redis:7-alpine + redis: + image: redis:7-alpine ports: ["6380:6379"] ``` -### 9.2 Systemd сервисы (продакшен) +### 10.3 Systemd сервисы (продакшен) -**Tracker:** Docker Compose + systemd unit -**BFF + Web Client:** systemd сервисы на хосте -**Picogent:** systemd unit на агента +- **Tracker:** Docker Compose + systemd unit +- **BFF + Web Client:** systemd на хосте +- **Picogent:** systemd unit на агента (один процесс = один сервис) +- **Nginx:** прокси + SSL/HTTPS -### 9.3 Nginx конфигурация +### 10.4 Nginx конфигурация ```nginx # Web Client @@ -582,12 +646,12 @@ location / { proxy_pass http://localhost:3100; } -# BFF API +# BFF API location /api/ { proxy_pass http://localhost:8200/api/; } -# BFF WebSocket +# BFF WebSocket location /ws { proxy_pass http://localhost:8200/ws; proxy_http_version 1.1; @@ -595,86 +659,115 @@ location /ws { proxy_set_header Connection "upgrade"; } -# Agent API (через nginx → Tracker) +# Agent API (nginx → Tracker) location /agent-api/ { proxy_pass http://localhost:8100/api/; } -# Agent WebSocket +# Agent WebSocket location /agent-ws { proxy_pass http://localhost:8100/ws; - proxy_http_version 1.1; + proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } ``` -### 9.4 SSL/HTTPS +### 10.5 Heartbeat и мониторинг -- **Dev:** `dev.team.uix.su` (действующий) -- **Prod:** `team.uix.su` (placeholder) -- **Cертификаты:** Let's Encrypt через certbot +- **systemd** перезапускает picogent при падении +- При reconnect агент делает `session.resume` +- Незавершённые задачи возвращаются в todo +- **Centralized logging** (JSON structured) -### 9.5 База данных +### 10.6 Git Workflow -- **Разработка:** PostgreSQL в Docker -- **Продакшен:** PostgreSQL на хосте -- **Миграции:** Нет (recreate from scratch) -- **Бэкапы:** pg_dump (TODO) - -### 9.6 Процесс деплоя - -1. **Git push** → git.uix.su/team-board/docs -2. **Manual deploy** на сервере -3. **Restart services:** systemctl restart team-board-* -4. **Health check:** /health endpoints - -**CI/CD:** Пока ручной деплой. В будущем — Gitea Actions. +- Агент клонит repo в рабочую директорию +- Работает в ветке `{type}/{task-key}-{slug}` +- По завершении → Merge Request в Gitea +- Ревью → approve/reject → автомерж +- Конфликты решает MR owner (макс 3 итерации) --- -## 10. Нереализованные части (TODO) +## 11. Ключевые решения из brainstorm-ов -### 10.1 Backend TODO +### 11.1 Архитектурные решения -- ❌ **Attachments API** — загрузка/скачивание файлов -- ❌ **Task events** через WebSocket — task.created/updated/assigned -- ❌ **Agent token auth** для REST API (только WS) -- ❌ **Chat threads** — parent_id поддержка в UI -- ❌ **Task dependencies** — визуализация и валидация -- ❌ **БД миграции** — пока только recreate +**✅ Unified Message модель** — одна таблица для чатов и комментариев задач (вместо отдельных ChatMessage и TaskComment). -### 10.2 Frontend TODO +**✅ Member + AgentConfig** — единая модель для людей и агентов (вместо отдельных User и Agent). -- ❌ **Task comments** в TaskModal -- ❌ **Task steps** (live progress) в TaskModal -- ❌ **Task watchers** — подписка/отписка -- ❌ **Agent management** — страница /agents -- ❌ **Project dashboard** — метрики и активность -- ❌ **Mobile UI** — адаптация под телефоны +**✅ Подзадачи vs Этапы:** подзадачи на канбане (parent_id), этапы внутри задачи (Steps). -### 10.3 Agent TODO +**✅ Watchers паттерн** — Jira-подобная подписка на задачи для получения уведомлений. -- ❌ **MCP Tools** — полный набор инструментов для picogent -- ❌ **Session resume** — восстановление контекста при переподключении -- ❌ **Multi-instance** — несколько экземпляров одного агента -- ❌ **Agent home** — workspace, memory, sessions +**✅ Listen modes раздельные** — chat_listen и task_listen независимы для гибкой фильтрации. -### 10.4 Infrastructure TODO +**❌ Redis Streams отклонён** — избыточно для MVP. WS для online + REST для reconnect достаточно. -- ❌ **Telegram Bridge** — дублирование чата в Telegram -- ❌ **OAuth/Authentik** — мультипользовательский режим -- ❌ **Redis integration** — event bus и кеширование -- ❌ **CI/CD pipeline** — автоматический деплой -- ❌ **Monitoring** — метрики и логи -- ❌ **Backup strategy** — регулярные бэкапы БД +### 11.2 Протокол решения + +**✅ WS = real-time, REST = мутации** — чёткое разделение ответственности. + +**✅ Фильтрация на сервере** — агент получает только релевантные события. + +**✅ Lazy Loading контекста** — агент при подключении НЕ грузит историю. + +**✅ Project Subscribe объединяет** — одна подписка даёт чат + task события. + +**✅ Router как text relay** — WS события → текст → единственная сессия агента. + +### 11.3 UI решения + +**✅ Drag & drop канбан** — с fallback на mobile tabs. + +**✅ TaskModal прогрессивно** — сначала базовые поля, потом комментарии/steps. + +**✅ Значки авторов** — 👤 человек, 🤖 агент, ⚙️ система в сообщениях. + +**✅ Threads только в чатах** — в задачах простая лента комментариев. + +### 11.4 Агентные решения + +**✅ Один binary — разные роли** — picogent + agent.json конфиг. + +**✅ Capabilities = лейблы** — автоматический matching задач и агентов. + +**✅ Агент может отклонить** — не безмолвный исполнитель, может отказаться с обоснованием. + +**✅ Checkpoint pattern** — короткие задачи + проверка входящих между шагами. + +**✅ Heartbeat мониторинг** — 30s интервал, 90s timeout → offline. + +### 11.5 Файловые решения + +**✅ Файлы = attachments** — нет отдельного файлового сервиса, всё через Message. + +**✅ Multi-repo проекты** — массив repo_urls вместо одного git_repo. + +**✅ Документация в описании** — ссылки на docs в Project.description или repo_urls. + +### 11.6 Отложенные/открытые решения + +**🔶 Реакции в чатах** — как обрабатывать emoji без засорения промпта агента. + +**🔶 Лейблы:** глобальные или per-project? + +**🔶 Multi-instance агентов:** slug = роль, instance_id для различения? + +**🔶 Telegram Bridge:** формат сообщений, топики, голосовые через Thoth. + +**🔶 OAuth/Authentik:** мультипользовательский режим (запланировано). + +### 11.7 Принципы проектирования + +**Минимум токенов:** Любая оптимизация оценивается с точки зрения раздувания MD-файлов контекста. Максимум логики в коде, минимум в MD. + +**Прогресс-апдейты:** При длительных операциях сообщать о прогрессе по ходу, не копить до конца. + +**Transparency First:** Всё видимо в чатах — создание задач, MR события, статусы агентов. --- -## Заключение - -Этот документ является единой точкой правды для всех концепций Team Board. Он основан на реальном коде и документации по состоянию на 2026-02-23. - -**Версионирование:** При значимых изменениях в архитектуре или API обновляется версия документа и дата. - -**Обратная связь:** Если код не соответствует документу — приоритет у кода (он правдивее), документ нужно обновить. \ No newline at end of file +*Документ создан на основе изучения 23 файлов документации Team Board по состоянию на 2026-02-23. Является единой точкой правды для всех концепций системы.* \ No newline at end of file