docs/migration-events.md

5.5 KiB
Raw Permalink Blame History

Миграция: messages → events

Цель

Единая таблица events вместо messages + task_actions. Один event = одно действие в системе.

Новая схема

Таблица events

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)

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.pyapi/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