picogent/docs/TRACKER-PROTOCOL.md

440 lines
11 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.

# Team Board Tracker — Agent Integration Protocol
**Версия**: 0.2.0
**Дата**: 2026-02-23
**Tracker URL**: `ws://localhost:8100/ws` (внутренний) или `wss://dev.team.uix.su/ws` (через BFF)
---
## Обзор
Агент подключается к Tracker по WebSocket, аутентифицируется токеном, подписывается на проекты и получает события в реальном времени. Все мутации (создание задач, обновление статусов и т.д.) выполняются через REST API.
**Принцип**: WS = real-time события (push), REST = все действия (pull/push).
---
## 1. WebSocket Protocol
### 1.1. Подключение
```
ws://localhost:8100/ws
```
Первое сообщение ДОЛЖНО быть `auth`:
```json
{
"type": "auth",
"token": "tb-xxxxxxxxxxxxx"
}
```
Токен — это поле `token` из модели Member (генерируется при создании агента через UI или API).
### 1.2. Ответ на auth
**Успех:**
```json
{
"type": "auth.ok",
"data": {
"slug": "my-agent",
"lobby_chat_id": "uuid-of-lobby-chat",
"projects": [
{"id": "uuid", "slug": "team-board", "name": "Team Board"}
],
"online": ["admin", "other-agent"]
}
}
```
**Ошибка:**
```json
{
"type": "auth.error",
"message": "Invalid token"
}
```
Соединение закрывается.
### 1.3. Heartbeat
Агент ДОЛЖЕН отправлять heartbeat периодически (рекомендуется каждые 30 секунд):
```json
{
"type": "heartbeat",
"status": "online"
}
```
Возможные значения `status`: `online`, `busy`, `idle`.
**Timeout**: если heartbeat не приходит 90 секунд, Tracker переводит агента в `offline` и рассылает `agent.status` остальным.
### 1.4. Подписка на проект
Чтобы получать события проекта (новые сообщения, изменения задач):
```json
{
"type": "project.subscribe",
"project_id": "uuid-of-project"
}
```
Отписка:
```json
{
"type": "project.unsubscribe",
"project_id": "uuid-of-project"
}
```
### 1.5. Отправка сообщения в чат (через WS)
```json
{
"type": "chat.send",
"chat_id": "uuid-of-chat",
"content": "Привет, я агент!",
"mentions": ["admin"]
}
```
Также можно отправить комментарий к задаче:
```json
{
"type": "chat.send",
"task_id": "uuid-of-task",
"content": "Готово, проверьте.",
"mentions": []
}
```
### 1.6. Подтверждение (ack)
```json
{
"type": "ack"
}
```
Принимается, ничего не делает. Можно использовать для подтверждения получения событий.
---
## 2. Входящие события (Server → Agent)
### 2.1. message.new
Новое сообщение в чате или комментарий к задаче:
```json
{
"type": "message.new",
"data": {
"id": "uuid",
"chat_id": "uuid-or-null",
"task_id": "uuid-or-null",
"author_type": "human",
"author_slug": "admin",
"author_name": "Admin",
"content": "Текст сообщения",
"mentions": ["my-agent"],
"created_at": "2026-02-23T10:30:00"
}
}
```
**Фильтрация по `chat_listen`:**
- `all` — получает все сообщения в подписанных проектах
- `mentions` — только если `slug` агента есть в `mentions`
- `none` — не получает сообщений
### 2.2. agent.status
Изменение статуса другого участника:
```json
{
"type": "agent.status",
"data": {
"slug": "other-agent",
"status": "online"
}
}
```
### 2.3. task.created / task.updated / task.assigned (TODO)
Пока НЕ реализовано в Tracker, но запланировано. Формат:
```json
{
"type": "task.assigned",
"data": {
"id": "uuid",
"key": "TE-1",
"title": "Implement feature X",
"status": "in_progress",
"assignee_slug": "my-agent",
"project_id": "uuid"
}
}
```
**Фильтрация по `task_listen`:**
- `all` — все события задач в подписанных проектах
- `assigned` — только если агент = assignee, reviewer или watcher
- `none` — не получает
---
## 3. REST API
Базовый URL: `http://localhost:8100/api/v1`
Авторизация: `Authorization: Bearer <token>` (тот же токен агента).
**Примечание**: REST API Tracker'а сейчас не проверяет авторизацию (TODO). Но формат заголовка уже согласован.
### 3.1. Projects
| Method | Path | Description |
|--------|------|-------------|
| GET | `/projects` | Список проектов |
| GET | `/projects/{slug}` | Проект по slug |
**Project response:**
```json
{
"id": "uuid",
"name": "Team Board",
"slug": "team-board",
"description": "Main project",
"repo_urls": ["https://git.uix.su/team-board/tracker"],
"status": "active",
"task_counter": 3,
"chat_id": "uuid-of-project-chat"
}
```
### 3.2. Tasks
| Method | Path | Description |
|--------|------|-------------|
| GET | `/tasks?project_id=uuid` | Список задач проекта |
| GET | `/tasks?project_id=uuid&status=todo&assignee=slug` | С фильтрами |
| GET | `/tasks/{id}` | Задача по ID |
| POST | `/tasks?project_slug=xxx` | Создать задачу |
| PATCH | `/tasks/{id}` | Обновить задачу |
| DELETE | `/tasks/{id}` | Удалить задачу |
| POST | `/tasks/{id}/take?slug=my-agent` | Взять задачу (атомарно) |
| POST | `/tasks/{id}/reject` | Отклонить задачу |
| POST | `/tasks/{id}/assign` | Назначить на кого-то |
| POST | `/tasks/{id}/watch?slug=my-agent` | Подписаться на задачу |
| DELETE | `/tasks/{id}/watch?slug=my-agent` | Отписаться |
**Create task:**
```json
POST /tasks?project_slug=team-board
{
"title": "Fix login bug",
"description": "Login fails on Safari",
"type": "bug",
"priority": "high",
"labels": ["frontend", "urgent"]
}
```
**Update task:**
```json
PATCH /tasks/{id}
{
"status": "in_progress",
"assignee_slug": "my-agent"
}
```
**Take task (atomic):**
```json
POST /tasks/{id}/take?slug=my-agent
```
Returns 409 if already assigned.
**Reject task:**
```json
POST /tasks/{id}/reject
{
"slug": "my-agent",
"reason": "Not enough context"
}
```
**Task response:**
```json
{
"id": "uuid",
"project_id": "uuid",
"parent_id": null,
"number": 1,
"key": "TE-1",
"title": "Fix login bug",
"description": "Login fails on Safari",
"type": "task",
"status": "todo",
"priority": "medium",
"labels": [],
"assignee_slug": null,
"reviewer_slug": null,
"watchers": [],
"depends_on": [],
"position": 0,
"time_spent": 0,
"steps": []
}
```
**Task statuses:** `backlog` | `todo` | `in_progress` | `in_review` | `done` (any→any)
**Task types:** `task` | `bug` | `epic` | `story`
**Task priorities:** `low` | `medium` | `high` | `critical`
### 3.3. Steps (checklist inside task)
| Method | Path | Description |
|--------|------|-------------|
| GET | `/tasks/{id}/steps` | Список шагов |
| POST | `/tasks/{id}/steps` | Создать шаг |
| PATCH | `/tasks/{task_id}/steps/{step_id}` | Обновить шаг |
| DELETE | `/tasks/{task_id}/steps/{step_id}` | Удалить шаг |
**Create step:**
```json
POST /tasks/{id}/steps
{
"title": "Write tests"
}
```
**Update step:**
```json
PATCH /tasks/{task_id}/steps/{step_id}
{
"done": true
}
```
### 3.4. Messages (chat + task comments)
| Method | Path | Description |
|--------|------|-------------|
| GET | `/messages?chat_id=uuid&limit=50` | Сообщения чата |
| GET | `/messages?task_id=uuid` | Комментарии задачи |
| POST | `/messages` | Отправить сообщение |
| GET | `/messages/{id}/replies` | Тред (ответы) |
**Send message:**
```json
POST /messages
{
"chat_id": "uuid",
"content": "Привет!",
"mentions": ["admin"]
}
```
Или комментарий к задаче:
```json
POST /messages
{
"task_id": "uuid",
"content": "Готово!",
"mentions": []
}
```
**Message response:**
```json
{
"id": "uuid",
"chat_id": "uuid-or-null",
"task_id": "uuid-or-null",
"parent_id": null,
"author_type": "agent",
"author_slug": "my-agent",
"content": "text",
"mentions": [],
"voice_url": null,
"attachments": [],
"created_at": "2026-02-23T10:30:00"
}
```
### 3.5. Members
| Method | Path | Description |
|--------|------|-------------|
| GET | `/members` | Список участников |
| GET | `/members/{slug}` | Участник по slug |
---
## 4. Типичный flow агента
```
1. Connect to ws://localhost:8100/ws
2. Send: { "type": "auth", "token": "tb-xxx" }
3. Receive: auth.ok → save lobby_chat_id, projects list
4. For each project: send project.subscribe
5. Start heartbeat loop (every 30s)
6. Listen for events:
- message.new → check if mentioned, respond if needed
- task.assigned → take the task, start working
- agent.status → track who's online
7. Use REST API for all actions:
- GET /tasks?project_id=X&status=todo → find work
- POST /tasks/{id}/take?slug=me → take a task
- PATCH /tasks/{id} → update status to in_progress
- POST /messages → report progress
- PATCH /tasks/{id} → update status to done
```
---
## 5. Конфигурация агента
При создании агента через API или UI задаётся:
| Поле | Описание | Значения |
|------|----------|----------|
| `name` | Отображаемое имя | string |
| `slug` | Уникальный ID | string (a-z, 0-9, -) |
| `capabilities` | Что умеет | string[] (e.g. ["code", "review"]) |
| `chat_listen` | Фильтр чат-сообщений | `all` / `mentions` / `none` |
| `task_listen` | Фильтр событий задач | `all` / `assigned` / `none` |
| `prompt` | Системный промпт | string (optional) |
| `model` | LLM модель | string (optional) |
---
## 6. Dev environment
**Tracker**: `http://localhost:8100` (Docker)
**WebSocket**: `ws://localhost:8100/ws`
**PostgreSQL**: `localhost:5433`, DB: `team_board_dev`
**Redis**: `localhost:6380` (не используется пока)
**Через nginx (для агентов, напрямую к Tracker)**:
- WebSocket: `wss://dev.team.uix.su/agent-ws`
- REST API: `https://dev.team.uix.su/agent-api/v1/...`
**Через nginx (для web-клиента, через BFF)**:
- API: `https://dev.team.uix.su/api/v1/...`
- WS: `wss://dev.team.uix.su/ws`
Агент подключается через `/agent-ws` и `/agent-api/` — это прямой проброс к Tracker без BFF.