docs/migration-events.md

132 lines
5.5 KiB
Markdown
Raw Permalink 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.

# Миграция: messages → events
## Цель
Единая таблица `events` вместо `messages` + `task_actions`. Один event = одно действие в системе.
## Новая схема
### Таблица `events`
```sql
CREATE TABLE events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id),
type VARCHAR(50) NOT NULL, -- см. типы ниже
actor_id UUID REFERENCES members(id), -- кто сделал
task_id UUID REFERENCES tasks(id) ON DELETE CASCADE, -- nullable
parent_id UUID REFERENCES events(id), -- для тредов
payload JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_events_project ON events(project_id, created_at);
CREATE INDEX idx_events_task ON events(task_id, created_at);
CREATE INDEX idx_events_type ON events(type);
```
### Таблица `attachments` (без изменений, переименуем FK)
```sql
ALTER TABLE attachments RENAME COLUMN message_id TO event_id;
```
### Типы событий
| type | payload | Где видно |
|------|---------|-----------|
| `chat_message` | `{content, mentions?, thinking?, voice_url?}` | Проектный чат |
| `task_comment` | `{content, mentions?, thinking?, tool_log?}` | Комментарии задачи |
| `task_created` | `{title, status, priority, assignee?}` | Чат + задача |
| `task_status` | `{from, to}` | Чат + задача |
| `task_assigned` | `{assignee, previous?}` | Чат + задача |
| `task_unassigned` | `{previous}` | Чат + задача |
| `task_updated` | `{field, from, to}` | Задача |
| `task_label_add` | `{label}` | Задача |
| `task_label_remove` | `{label}` | Задача |
### Что удаляем
- Таблица `messages` → заменена `events`
- Таблица `task_actions` → заменена `events` (type = task_*)
- Таблица `chats`**удаляем** (project_id в events заменяет chat routing)
- Колонка `author_type` → заменена на `type` + `actor_id` (system events = actor_id NULL)
### Что НЕ меняем
- `tasks`, `projects`, `members`, `agent_configs`, `labels`, `steps`, `project_files`, `task_labels`, `task_links`
---
## План миграции (6 этапов)
### Этап 1: Backend — модели
- [ ] Создать `models/event.py` с Event model
- [ ] Удалить `models/message.py`, `models/task_action.py`
- [ ] Удалить `models/chat.py`
- [ ] Обновить `__init__.py` — импорты
### Этап 2: Backend — API
- [ ] Переписать `api/messages.py``api/events.py`
- `POST /api/v1/events` — создать event (chat_message, task_comment)
- `GET /api/v1/events?project_id=X&types=chat_message,task_status,...&limit=N` — лента проекта
- `GET /api/v1/events?task_id=X` — лента задачи
- [ ] Обновить `api/tasks.py` — создавать events вместо messages + task_actions
- Одна запись вместо двух (task comment + chat message → один event)
- [ ] Обновить `api/schemas.py` — EventOut, EventCreate
- [ ] Удалить эндпоинты `/messages` (или оставить как alias)
### Этап 3: Backend — WebSocket
- [ ] WS broadcast: `event.new` вместо `message.new`
- [ ] Streaming: `agent.stream.*` — без изменений (task_id привязка)
- [ ] Обновить `ws/manager.py` — broadcast по project_id (уже есть)
### Этап 4: Backend — Picogent tools
- [ ] `send_message` tool → отправляет `POST /api/v1/events` с type=task_comment
- [ ] `list_messages` tool → `GET /api/v1/events?task_id=X`
- [ ] Обновить TrackerClient в picogent
### Этап 5: Frontend
- [ ] `lib/api.ts` — новые типы Event, эндпоинты
- [ ] `ChatPanel.tsx` — рендерит events вместо messages
- `chat_message` → обычное сообщение
- `task_status` → системное "TE-4: backlog → done"
- `task_assigned` → системное "TE-4: назначена на @coder"
- `task_created` → системное "TE-4 создана: ..."
- [ ] `TaskModal.tsx` — комментарии из events (type=task_comment + task_status + ...)
- [ ] `MentionInput.tsx` — без изменений
- [ ] WS: слушать `event.new` вместо `message.new`
- [ ] Streaming — без изменений
### Этап 6: База данных
- [ ] DROP TABLE messages, task_actions, chats
- [ ] CREATE TABLE events (через SQLAlchemy create_all при dev start)
- [ ] Seed: создать тестовый проект заново
---
## Запросы для фронта
**Проектный чат:**
```
GET /api/v1/events?project_id=X&types=chat_message,task_created,task_status,task_assigned,task_unassigned&limit=30
```
**Комментарии задачи:**
```
GET /api/v1/events?task_id=X&limit=50
```
**Timeline проекта (всё):**
```
GET /api/v1/events?project_id=X&limit=100
```
---
## Оценка
- Backend: ~4 часа
- Frontend: ~2 часа
- Тесты: ~1 час
- **Итого: ~1 день**
## Риски
- Bridge (Telegram) — нужно обновить, он создаёт messages через API
- Picogent — нужно обновить send_message/list_messages tools
- Тесты — переписать test_chat.py, test_messages.py