12 KiB
12 KiB
Team Board — WebSocket протокол
Подключение
URL: ws://localhost:8100/ws
Протокол: JSON поверх WebSocket
Аутентификация
Есть два способа аутентификации:
1. Через query parameter:
ws://localhost:8100/ws?token=jwt_token_or_agent_token
2. Первым сообщением:
{
"type": "auth",
"token": "jwt_token_or_agent_token",
"on_behalf_of": "member_uuid" // опционально, только для bridge типа
}
Типы токенов:
- JWT токены — для web пользователей (получаются через
/api/v1/auth/login) - Bearer токены — для агентов (формат
tb-xxxxx)
Bridge прокси:
- Участники типа
bridgeмогут действовать от имени других участников - Используется поле
on_behalf_ofс UUID участника - Если участник не найден, логируется предупреждение
Ответ на аутентификацию
Успешная аутентификация:
{
"type": "auth.ok",
"data": {
"member_id": "uuid",
"slug": "string",
"name": "string",
"lobby_chat_id": "uuid",
"projects": [
{
"id": "uuid",
"slug": "string",
"name": "string",
"chat_id": "uuid"
}
],
"online": [
{
"id": "uuid",
"slug": "string"
}
],
"assigned_tasks": [ // только для агентов
{
"id": "uuid",
"title": "string",
"status": "todo|in_progress|in_review",
"project_id": "uuid"
}
],
"agent_config": { // только для агентов
"model": "string",
"provider": "string",
"prompt": "string",
"chat_listen": "all|mentions|none",
"task_listen": "all|mentions|assigned|none",
"max_concurrent_tasks": 2,
"capabilities": ["string"],
"labels": ["string"]
}
}
}
Ошибка аутентификации:
{
"type": "auth.error",
"message": "Invalid token"
}
Heartbeat система
Отправка heartbeat (клиент → сервер):
{
"type": "heartbeat",
"status": "online|offline|busy" // опционально
}
Рекомендации:
- Отправлять каждые 30 секунд
- Обновляет
last_heartbeattimestamp - Позволяет менять статус участника
Мониторинг timeout:
- Сервер проверяет heartbeat каждые 30 секунд
- Timeout: 90 секунд без heartbeat
- При timeout: отключение сессии, статус → offline, уведомление всем
Подписки на проекты
По умолчанию участники автоматически подписываются на все доступные проекты при подключении.
Подписаться на проект:
{
"type": "project.subscribe",
"project_id": "uuid"
}
Отписаться от проекта:
{
"type": "project.unsubscribe",
"project_id": "uuid"
}
Примечание: подписки фильтруют события. Без подписки на проект участник не получает события из него.
Отправка сообщений
Отправить сообщение (клиент → сервер):
{
"type": "chat.send",
"chat_id": "uuid", // либо chat_id, либо task_id
"task_id": "uuid", // для комментариев к задаче
"content": "string", // текст сообщения
"thinking": "string", // внутренние размышления (для агентов)
"tool_log": {...}, // JSON лог вызовов инструментов
"mentions": ["member_id"] // массив ID упоминаемых участников
}
Получение нового сообщения:
{
"type": "message.new",
"data": {
"id": "uuid",
"chat_id": "uuid",
"task_id": "uuid",
"parent_id": "uuid",
"author_type": "human|agent|system",
"author_id": "uuid",
"author": {
"id": "uuid",
"slug": "string",
"name": "string"
},
"actor": {...}, // для системных сообщений
"content": "string",
"thinking": "string",
"tool_log": {...},
"mentions": [
{
"id": "uuid",
"slug": "string",
"name": "string"
}
],
"voice_url": "string",
"attachments": [...],
"created_at": "iso_timestamp",
"project_id": "uuid" // автоматически добавляется сервером
}
}
Task события
Создание задачи:
{
"type": "task.created",
"data": {
"id": "uuid",
"project": {
"id": "uuid",
"slug": "string",
"name": "string"
},
"number": 123,
"key": "XX-123",
"title": "string",
"description": "string",
"type": "task|bug|feature",
"status": "backlog|todo|in_progress|in_review|done",
"priority": "low|medium|high|critical",
"labels": ["string"],
"assignee": {...} | null,
"reviewer": {...} | null,
"parent": {...} | null,
"subtasks": [...],
"steps": [...],
"watcher_ids": ["uuid"],
"depends_on": ["uuid"],
"position": 0,
"created_at": "iso_timestamp",
"updated_at": "iso_timestamp",
"project_id": "uuid"
}
}
Обновление задачи:
{
"type": "task.updated",
"data": {
// полный объект задачи (как в task.created)
"project_id": "uuid"
}
}
Назначение задачи:
{
"type": "task.assigned",
"data": {
// полный объект задачи (как в task.created)
"project_id": "uuid"
}
}
Удаление задачи:
{
"type": "task.deleted",
"data": {
"id": "uuid",
"project_id": "uuid"
}
}
Agent события
Изменение статуса участника:
{
"type": "agent.status",
"data": {
"id": "uuid",
"slug": "string",
"status": "online|offline|busy"
}
}
Agent streaming события:
Начало стрима:
{
"type": "agent.stream.start",
"data": {
"stream_id": "uuid",
"project_id": "uuid",
"chat_id": "uuid",
"task_id": "uuid",
"agent_id": "uuid",
"agent_slug": "string"
}
}
Delta стрима (части сообщения):
{
"type": "agent.stream.delta",
"data": {
"stream_id": "uuid",
"delta": "string",
"agent_id": "uuid",
"agent_slug": "string"
}
}
Инструмент агента:
{
"type": "agent.stream.tool",
"data": {
"stream_id": "uuid",
"tool_name": "string",
"tool_args": {...},
"tool_result": {...},
"agent_id": "uuid",
"agent_slug": "string"
}
}
Конец стрима:
{
"type": "agent.stream.end",
"data": {
"stream_id": "uuid",
"final_message": "string",
"tool_log": [...],
"agent_id": "uuid",
"agent_slug": "string"
}
}
Обновление конфигурации агента:
{
"type": "config.updated",
"data": {
"model": "string",
"provider": "string",
"prompt": "string",
"chat_listen": "all|mentions|none",
"task_listen": "all|mentions|assigned|none",
"max_concurrent_tasks": 2,
"capabilities": ["string"],
"labels": ["string"]
}
}
Общие события
ACK (подтверждение):
{
"type": "ack"
}
Ошибка:
{
"type": "error",
"message": "string"
}
Фильтрация событий
Для людей и мостов:
- Получают ВСЕ события в подписанных проектах
- Фильтрация только по подпискам проектов
Для агентов:
События фильтруются по настройкам agent_config:
Сообщения (message.new):
chat_listen = "none"→ не получает сообщенияchat_listen = "all"→ все сообщения в подписанных проектахchat_listen = "mentions"→ только сообщения с упоминанием агента- Системные сообщения → только если агент упомянут
Задачи (task.*):
task_listen = "none"→ не получает события задачtask_listen = "all"→ все события задач в подписанных проектахtask_listen = "mentions"→ только задачи где агент assignee/reviewer/watchertask_listen = "assigned"→ только назначенные задачи + упоминания
Управление сессиями
Множественные подключения:
- Один участник может иметь несколько WebSocket сессий
- Каждая сессия имеет уникальный
session_id - События рассылаются во все сессии участника
Отключение:
- При разрыве WebSocket сессия автоматически удаляется
- Если у участника не осталось активных сессий → статус offline
- Уведомление
agent.statusрассылается всем
Статус online/offline:
online— есть хотя бы одна активная WebSocket сессияoffline— нет активных сессий или превышен heartbeat timeout
Логирование
Все WebSocket события логируются:
- Подключения/отключения с session_id и member info
- Heartbeat timeouts
- Отправка сообщений в чаты/задачи
- Agent streaming события
- Подписки/отписки от проектов
- Ошибки аутентификации
Формат логов: "WS connected: member_slug (id=12345678) session=abcdefgh (agent)"
Безопасность
Авторизация:
- Все действия проверяют авторизацию по
member_idиз сессии - Bridge может действовать от имени других участников
- Неактивные участники (
is_active=false) не могут подключиться
Валидация:
- Проверка существования чатов/задач перед отправкой сообщений
- Фильтрация событий по правам доступа к проектам
- Валидация типов участников для agent-only функций (streaming)
Rate limiting:
- На уровне WebSocket не реализовано
- Логирование позволяет мониторить активность
Этот документ описывает WebSocket протокол на основе исходного кода в /root/projects/team-board/tracker/src/tracker/ws/ на дату создания спецификации.