Справочная документация по WebSocket API¶
В этом документе описывается WebSocket API для работы с CodeGraph в режиме реального времени.
Содержание¶
- Обзор
- Аутентификация
- Ошибки соединения
- Точки доступа (Endpoints)
- Потоковая передача чата
- Статус задачи
- Уведомления
- Типы сообщений
- Клиент → Сервер
- Сервер → Клиент
- Формат сообщений
- Поддержание соединения (Keep-Alive)
- Обработка ошибок
- Формат сообщения об ошибке
- Распространённые ошибки
- Пример клиента на Python
- Пример клиента на JavaScript
- Ограничения по частоте запросов (Rate Limits)
- См. также
Обзор¶
WebSocket API предоставляет: - Потоковую передачу ответов чата — потоковую передачу ответов ИИ в реальном времени - Обновления хода выполнения задач — уведомления о состоянии фоновых задач - Push-уведомления — системные оповещения и уведомления
Базовый URL: ws://localhost:8000/ws/v1
Аутентификация¶
Все соединения WebSocket требуют JWT-токен, передаваемый в качестве параметра запроса.
ws://localhost:8000/ws/v1/chat?token=<JWT_TOKEN>
Ошибки соединения¶
| Код | Причина | Описание |
|---|---|---|
| 4001 | Недействительный токен | Токен отсутствует, просрочен или недействителен |
| 4003 | Доступ запрещён | У пользователя недостаточно прав |
| 1008 | Нарушение политики | Ошибка политики соединения |
Конечные точки¶
Потоковый чат¶
Конечная точка: ws://localhost:8000/ws/v1/chat
Общение в реальном времени с потоковой передачей ответов.
Подключение¶
const ws = new WebSocket('ws://localhost:8000/ws/v1/chat?token=' + token);
ws.onopen = () => {
console.log('Подключено к чату');
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Получено:', message.type, message.payload);
};
ws.onerror = (error) => {
console.error('Ошибка WebSocket:', error);
};
ws.onclose = (event) => {
console.log('Отключено:', event.code, event.reason);
};
Отправка запроса в чат¶
ws.send(JSON.stringify({
type: 'chat.query',
payload: {
query: 'Найти все уязвимости к SQL-инъекциям',
session_id: 'необязательный-id-сессии',
scenario_id: 'необязательный-id-сценария',
language: 'en'
},
request_id: 'уникальный-id-запроса'
}));
Получение потокового ответа¶
Сообщения приходят последовательно:
- Выбор сценария (необязательно)
{
"type": "chat.scenario",
"payload": { "scenario_id": "security_audit" },
"timestamp": "2025-12-14T10:30:00Z",
"request_id": "unique-request-id"
}
- Фрагменты ответа (несколько)
{
"type": "chat.chunk",
"payload": { "content": "Найдено 3 потенциальные ", "is_final": false },
"timestamp": "2025-12-14T10:30:01Z",
"request_id": "unique-request-id"
}
- Завершение
{
"type": "chat.done",
"payload": {},
"timestamp": "2025-12-14T10:30:05Z",
"request_id": "unique-request-id"
}
Статус задачи¶
Конечная точка: ws://localhost:8000/ws/v1/jobs/{job_id}
Подписка на обновления хода выполнения фоновой задачи.
Подключение¶
const jobId = 'abc123';
const ws = new WebSocket(`ws://localhost:8000/ws/v1/jobs/${jobId}?token=${token}`);
Сообщения¶
Задача запущена
{
"type": "job.started",
"payload": {
"job_id": "abc123",
"status": "subscribed"
},
"timestamp": "2025-12-14T10:30:00Z"
}
Ход выполнения задачи
{
"type": "job.progress",
"payload": {
"job_id": "abc123",
"status": "running",
"progress": 45,
"message": "Обработка файлов..."
},
"timestamp": "2025-12-14T10:31:00Z"
}
Задача завершена
{
"type": "job.completed",
"payload": {
"job_id": "abc123",
"status": "completed",
"progress": 100,
"result": {
"files_processed": 150,
"vulnerabilities_found": 3
}
},
"timestamp": "2025-12-14T10:35:00Z"
}
Задача завершилась с ошибкой
{
"type": "job.failed",
"payload": {
"job_id": "abc123",
"status": "failed",
"error": "Таймаут соединения",
"details": "Не удалось подключиться к серверу Joern"
},
"timestamp": "2025-12-14T10:35:00Z"
}
Уведомления¶
Конечная точка: ws://localhost:8000/ws/v1/notifications
Получение push-уведомлений о системных событиях.
Подключение¶
const ws = new WebSocket('ws://localhost:8000/ws/v1/notifications?token=' + token);
Сообщения¶
Уведомление
{
"type": "notification",
"payload": {
"title": "Импорт завершён",
"message": "Проект 'myapp' успешно импортирован",
"level": "success",
"action_url": "/projects/abc123"
},
"timestamp": "2025-12-14T10:35:00Z"
}
Уровни уведомлений: info, success, warning, error
Типы сообщений¶
Клиент → Сервер¶
| Тип | Описание | Полезная нагрузка |
|---|---|---|
| chat.query | Отправить запрос в чат | query,session_id?,scenario_id?,language? |
| ping | Поддержание соединения | Нет |
Сервер → Клиент¶
| Тип | Описание | Полезная нагрузка |
|---|---|---|
| chat.scenario | Выбор сценария | scenario_id |
| chat.chunk | Фрагмент ответа | content,is_final |
| chat.done | Ответ завершён | Нет |
| chat.error | Ошибка чата | error,details? |
| job.started | Задача подписана | job_id,status |
| job.progress | Ход выполнения задачи | job_id,status,progress,message? |
| job.completed | Задача завершена | job_id,result |
| job.failed | Задача не удалась | job_id,error,details? |
| notification | Уведомление | title,message,level,action_url? |
| error | Общая ошибка | error,details? |
| pong | Ответ на ping | Нет |
Формат сообщения¶
Все сообщения имеют следующую структуру:
interface WSMessage {
type: string; // Тип сообщения (например, 'chat.query')
payload: object; // Данные, специфичные для сообщения
timestamp?: string; // Временная метка в формате ISO 8601
request_id?: string; // Для сопоставления запросов и ответов
}
Сохранение соединения¶
Отправляйте периодические ping-сообщения, чтобы предотвратить таймаут соединения:
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping', payload: {} }));
}
}, 30000); // Каждые 30 секунд
Обработка ошибок¶
Формат сообщения об ошибке¶
{
"type": "error",
"payload": {
"error": "Описание ошибки",
"details": "Дополнительные сведения"
},
"request_id": "original-request-id"
}
Распространённые ошибки¶
| Ошибка | Причина | Решение |
|---|---|---|
| Неверный формат сообщения | Некорректный JSON | Проверьте структуру сообщения |
| Требуется запрос | Пустой запрос | Укажите текст запроса |
| Неизвестный тип сообщения | Неподдерживаемый тип | Используйте типы, описанные в документации |
| Задача не найдена | Неверный идентификатор задачи | Убедитесь, что задача существует |
Пример клиента на Python¶
import asyncio
import json
import websockets
async def chat_client(token: str, query: str):
uri = f"ws://localhost:8000/ws/v1/chat?token={token}"
async with websockets.connect(uri) as ws:
# Отправка запроса
await ws.send(json.dumps({
"type": "chat.query",
"payload": {"query": query},
"request_id": "req-001"
}))
# Получение потокового ответа
full_response = ""
async for message in ws:
data = json.loads(message)
if data["type"] == "chat.chunk":
content = data["payload"]["content"]
full_response += content
print(content, end="", flush=True)
elif data["type"] == "chat.done":
print("\n--- Ответ завершён ---")
break
elif data["type"] == "error":
print(f"Ошибка: {data['payload']['error']}")
break
return full_response
# Использование {#usage}
asyncio.run(chat_client("your-jwt-token", "Найди переполнения буфера"))
Пример JavaScript-клиента¶
class ChatClient {
constructor(token) {
this.token = token;
this.ws = null;
this.handlers = new Map();
}
connect() {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(
`ws://localhost:8000/ws/v1/chat?token=${this.token}`
);
this.ws.onopen = () => resolve(this);
this.ws.onerror = (error) => reject(error);
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
const handler = this.handlers.get(message.request_id);
if (handler) {
handler(message);
}
};
});
}
async query(text, onChunk) {
const requestId = `req-${Date.now()}`;
return new Promise((resolve, reject) => {
let fullResponse = '';
this.handlers.set(requestId, (message) => {
switch (message.type) {
case 'chat.chunk':
fullResponse += message.payload.content;
onChunk?.(message.payload.content);
break;
case 'chat.done':
this.handlers.delete(requestId);
resolve(fullResponse);
break;
case 'error':
this.handlers.delete(requestId);
reject(new Error(message.payload.error));
break;
}
});
this.ws.send(JSON.stringify({
type: 'chat.query',
payload: { query: text },
request_id: requestId
}));
});
}
close() {
this.ws?.close();
}
}
// Использование
const client = await new ChatClient('jwt-token').connect();
const response = await client.query(
'Найти SQL-инъекции',
(chunk) => process.stdout.write(chunk)
);
console.log('\nПолный ответ:', response);
client.close();
Ограничения по скорости¶
| Ограничение | Значение | Описание |
|---|---|---|
| Макс. количество соединений на пользователя | 5 | Одновременные WebSocket-соединения |
| Макс. размер сообщения | 64 КБ | Полезная нагрузка одного сообщения |
| Сообщений в секунду | 10 | Ограничение скорости на одно соединение |
| Интервал ping | 30 сек | Рекомендуемый интервал для поддержания соединения |
| Таймаут соединения | 5 мин | Таймаут неактивного соединения |
Смотрите также¶
- Справочник по REST API — документация по HTTP API