# Работа с WebSocket соединениями

В этом разделе описаны возможности SDK для работы с WebSocket соединениями, методы управления сессиями рассуждений, диагностика соединений и дополнительные возможности для обеспечения стабильной работы.

## Содержание

- [Основы работы с WebSocket](#основы-работы-с-websocket)
- [Высокоуровневый API (версия 1.7.2)](#высокоуровневый-api-версия-172)
- [Потоковая передача мышления](#потоковая-передача-мышления)
- [Управление сессиями рассуждений](#управление-сессиями-рассуждений)
- [Диагностика соединений](#диагностика-соединений)
- [Механизм переподключения](#механизм-переподключения)
- [Сохранение и восстановление сессий](#сохранение-и-восстановление-сессий)
- [Проверка здоровья соединений](#проверка-здоровья-соединений)
- [Работа с ping/pong](#работа-с-pingpong)
- [Примеры использования](#примеры-использования)
- [Справочник всех событий WebSocket](#справочник-всех-событий-websocket)

## Основы работы с WebSocket

SDK предоставляет низкоуровневый WebSocket клиент (`CodeSolverWebSocketClient`), который используется для связи с различными пространствами имен сервера:

```javascript
const { CodeSolverSDK } = require('solver-sdk');

const sdk = new CodeSolverSDK({
  baseURL: 'https://api.example.com',
  apiKey: 'your-api-key'
});

// Получение WebSocket клиента
const wsClient = sdk.getWebSocketClient();

// Подключение к пространству имен рассуждений
await wsClient.connectToReasoning('reasoning-id');

// Проверка состояния подключения
const isConnected = wsClient.isConnectedToReasoning();
console.log('Подключено к рассуждениям:', isConnected);

// Подписка на события
wsClient.on('thinking_delta', (data) => {
  console.log('Получен фрагмент мышления:', data.text);
});

// Отключение
wsClient.disconnect(WebSocketNamespace.REASONING);
```

## Высокоуровневый API (версия 1.7.2)

Начиная с версии 1.7.2, SDK предоставляет высокоуровневый API для работы с WebSocket, интегрированный непосредственно в основные классы API:

### Работа с чатом и рассуждениями

```javascript
// Подключение WebSocket для чата
await sdk.chat.connectWebSocket();

// Подписка на события
sdk.chat.on('message_start', (data) => {
  console.log('Начало сообщения:', data);
});

sdk.chat.on('thinking_delta', (data) => {
  console.log('Фрагмент мышления:', data.text);
});

// Отключение 
await sdk.chat.disconnectWebSocket();
```

### Работа с зависимостями

```javascript
// Подключение к пространству имен зависимостей
await sdk.dependencies.connectWebSocket(projectId);

// Подписка на события зависимостей
sdk.dependencies.on('dependency_update', (data) => {
  console.log('Обновление зависимостей:', data);
});

// Отключение
await sdk.dependencies.disconnectWebSocket();
```

### Работа с проектами и индексацией

```javascript
// Подключение к пространству имен проектов
await sdk.projects.connectWebSocket();

// Подписка на события индексации
sdk.projects.on('indexing_progress', (data) => {
  console.log('Прогресс индексации:', data.progress);
});

// Отключение
await sdk.projects.disconnectWebSocket();
```

## Потоковая передача мышления

В версии 1.7.2 добавлена полная поддержка потоковой передачи мышления через метод `streamChatWithThinking`:

```javascript
// Обработчик событий
const handleEvent = (eventType, data) => {
  switch(eventType) {
    case 'thinking_delta':
      console.log('Мышление:', data.text);
      break;
    case 'text_delta':
      console.log('Ответ:', data.text);
      break;
    case 'message_start':
      console.log('Начало сообщения');
      break;
    case 'message_stop':
      console.log('Завершение ответа');
      break;
  }
};

// Отправка запроса с потоковым мышлением
const messages = [
  { role: 'user', content: 'Как работает квантовый компьютер?' }
];

const options = {
  model: 'claude-3-7-sonnet-20240229',
  thinking: true,
  temperature: 0.7
};

const response = await sdk.chat.streamChatWithThinking(
  messages,
  options,
  handleEvent
);
```

### Поддерживаемые события мышления

SDK поддерживает следующие ключевые события:

| Событие | Описание | Данные |
|---------|----------|--------|
| `message_start` | Начало сообщения | `{ model: string, type: string }` |
| `content_block_start` | Начало блока контента | `{ index: number, type: string }` |
| `thinking_delta` | Фрагмент мышления | `{ text: string, index: number }` |
| `text_delta` | Фрагмент ответа | `{ text: string, index: number }` |
| `content_block_stop` | Завершение блока контента | `{ index: number, type: string }` |
| `message_stop` | Завершение сообщения | `{ type: string }` |

## Управление сессиями рассуждений

SDK версии 1.7.0+ предоставляет расширенные возможности для управления сессиями рассуждений:

### Установка активной сессии рассуждения

```javascript
// Простая установка активного ID рассуждения
wsClient.setActiveReasoningId('reasoning-id');

// Расширенный вариант с дополнительными возможностями
await wsClient.setActiveReasoningIdAsync(
  'reasoning-id', // ID рассуждения (можно передать null для создания нового)
  true,           // waitForJoin: ждать результата присоединения
  true            // createIfNotExists: создать новое, если не существует
);
```

### Создание нового рассуждения

```javascript
// Создание нового рассуждения и получение его ID
const newReasoningId = await wsClient.createNewReasoning();
console.log('Создано новое рассуждение:', newReasoningId);
```

### Проверка существования рассуждения

```javascript
// Проверка существования рассуждения на сервере
const exists = await wsClient.checkReasoningExists('reasoning-id');
if (exists) {
  console.log('Рассуждение существует');
} else {
  console.log('Рассуждение не найдено');
}
```

### Получение статуса рассуждения

```javascript
// Получение детальной информации о сессии рассуждения
const status = await wsClient.getReasoningStatus('reasoning-id');
console.log('Статус:', status.exists, status.isActive);
console.log('Метаданные:', status.metadata);
```

### Присоединение к сессии рассуждения

```javascript
// Явное присоединение к существующей сессии
const joined = await wsClient.joinReasoning(
  'reasoning-id',
  true // setActive: установить как активное рассуждение
);

if (joined) {
  console.log('Успешно присоединились к рассуждению');
} else {
  console.log('Не удалось присоединиться к рассуждению');
}
```

## Диагностика соединений

SDK предоставляет методы для диагностики состояния соединений и получения подробной информации о них:

```javascript
// Диагностика конкретного соединения
const diagnostics = wsClient.diagnoseConnection(WebSocketNamespace.REASONING);
console.log('Диагностика соединения:', diagnostics);

// Диагностика всех активных соединений
const allDiagnostics = wsClient.diagnoseAllConnections();
console.log('Все соединения:', allDiagnostics);
```

Результат диагностики содержит следующую информацию:

```typescript
interface ConnectionDiagnostics {
  namespace: WebSocketNamespace;  // Пространство имен
  isConnected: boolean;          // Активно ли соединение
  socketId: string | null;       // ID сокета
  lastActivity: number;          // Время последней активности
  rtt: {                         // Round Trip Time (задержка)
    current: number;             // Текущая задержка
    min: number;                 // Минимальная задержка
    max: number;                 // Максимальная задержка
    avg: number;                 // Средняя задержка
  };
  pingSent: number;              // Отправлено ping-сообщений
  pongReceived: number;          // Получено pong-ответов
  missedPongs: number;           // Пропущено pong-ответов
  timeoutCount: number;          // Количество таймаутов
  reconnectAttempts: number;     // Количество попыток переподключения
  lastConnectTime: number;       // Время последнего подключения
  sessionRecovery: {             // Информация о восстановлении сессии
    hasSessionToken: boolean;    // Наличие токена сессии
    tokenLength: number;         // Длина токена сессии
    wasRecovered: boolean;       // Было ли восстановлено из сессии
  };
}
```

## Механизм переподключения

SDK реализует интеллектуальный механизм переподключения с экспоненциальной задержкой и случайным фактором (jitter) для предотвращения штормов переподключений:

```javascript
// Настройка параметров переподключения при создании SDK
const sdk = new CodeSolverSDK({
  baseURL: 'https://api.example.com',
  apiKey: 'your-api-key',
  websocket: {
    reconnect: true,               // Включить автоматическое переподключение
    reconnectStrategy: 'exponential', // 'linear' или 'exponential'
    retryDelay: 1000,                // Базовая задержка в миллисекундах
    maxRetryDelay: 30000,            // Максимальная задержка
    reconnectAttempts: 5             // Максимальное количество попыток
  }
});

// Принудительное переподключение к пространству имен
await wsClient.reconnectNamespace(
  WebSocketNamespace.REASONING,
  true // immediate: переподключиться немедленно, без задержки
);
```

## Сохранение и восстановление сессий

SDK поддерживает механизм сохранения и восстановления токенов сессий для непрерывной работы при переподключениях:

```javascript
// Явное сохранение токена сессии
wsClient.saveSessionToken(WebSocketNamespace.REASONING, 'session-token');

// Получение сохраненного токена
const token = wsClient.getSessionToken(WebSocketNamespace.REASONING);

// Очистка токена сессии
wsClient.clearSessionToken(WebSocketNamespace.REASONING);

// Включение/отключение сохранения сессий при создании SDK
const sdk = new CodeSolverSDK({
  baseURL: 'https://api.example.com',
  apiKey: 'your-api-key',
  websocket: {
    enableSessionPersistence: true // Включить сохранение токенов сессий
  }
});
```

## Проверка здоровья соединений

SDK предоставляет механизм регулярной проверки здоровья соединений и автоматического переподключения при обнаружении проблем:

```javascript
// Настройка проверки здоровья соединений
wsClient.setupConnectionHealthCheck(
  30000 // Интервал проверки в миллисекундах
);

// Отключение проверки здоровья
if (wsClient.healthCheckTimer) {
  clearInterval(wsClient.healthCheckTimer);
  wsClient.healthCheckTimer = null;
}
```

## Работа с ping/pong

Для поддержания активных соединений и измерения времени отклика SDK использует механизм ping/pong:

```javascript
// Включение автоматического ping/pong
wsClient.enablePingPong(
  15000, // Интервал между ping-сообщениями (мс)
  3      // Порог таймаута (количество пропущенных pong)
);

// Отключение механизма ping/pong
wsClient.disablePingPong();

// Получение статистики ping/pong
const stats = wsClient.getPingStats(WebSocketNamespace.REASONING);
console.log('Статистика ping/pong:', stats);

// Подписка на события таймаута соединения
wsClient.onPingPongEvent('connection_timeout', (data) => {
  console.log('Таймаут соединения:', data);
});
```

## Примеры использования

### Работа с потоковой передачей мышления

```javascript
const { CodeSolverSDK } = require('solver-sdk');

async function streamingThinking() {
  const sdk = new CodeSolverSDK({
    baseURL: 'https://api.example.com',
    apiKey: 'ваш-ключ-api',
    websocket: {
      reconnect: true,
      pingInterval: 30000
    }
  });
  
  // Подключаем WebSocket
  await sdk.chat.connectWebSocket();
  
  // Создаем буферы для накопления контента
  let thinkingBuffer = '';
  let responseBuffer = '';
  
  // Настраиваем обработчик событий
  const handleEvent = (eventType, data) => {
    switch(eventType) {
      case 'thinking_delta':
        thinkingBuffer += data.text || '';
        // Обновляем UI с мышлением
        updateThinkingUI(thinkingBuffer);
        break;
        
      case 'text_delta':
        responseBuffer += data.text || '';
        // Обновляем UI с ответом
        updateResponseUI(responseBuffer);
        break;
        
      case 'message_stop':
        console.log('Обработка завершена');
        break;
    }
  };
  
  // Отправляем запрос
  const messages = [
    { role: 'user', content: 'Объясни принцип работы квантового компьютера' }
  ];
  
  try {
    const response = await sdk.chat.streamChatWithThinking(
      messages,
      {
        model: 'claude-3-7-sonnet-20240229',
        thinking: true,
        temperature: 0.7
      },
      handleEvent
    );
    
    console.log('Запрос отправлен, ID сокета:', response.socketId);
    
    // После завершения можно отключиться
    setTimeout(() => {
      sdk.chat.disconnectWebSocket();
      console.log('Соединение закрыто');
    }, 1000);
    
    return {
      thinking: thinkingBuffer,
      response: responseBuffer
    };
  } catch (error) {
    console.error('Ошибка при отправке запроса:', error);
    sdk.chat.disconnectWebSocket();
    throw error;
  }
}

// Функции для обновления UI
function updateThinkingUI(text) {
  console.log('Обновление блока мышления');
  // document.getElementById('thinking-container').textContent = text;
}

function updateResponseUI(text) {
  console.log('Обновление блока ответа');
  // document.getElementById('response-container').textContent = text;
}

// Запуск функции
streamingThinking().catch(console.error);
```

### Работа с региональным переключением

```javascript
const { CodeSolverSDK } = require('solver-sdk');

async function chatWithRegionalFailover() {
  const sdk = new CodeSolverSDK({
    baseURL: 'https://api.example.com',
    apiKey: 'ваш-ключ-api',
    providers: {
      anthropic: {
        region: 'us-east-1' // Базовый регион
      }
    }
  });
  
  // Подключаем WebSocket
  await sdk.chat.connectWebSocket();
  
  // Настраиваем обработчик для отображения региона и ошибок
  sdk.chat.on('region_switch', (data) => {
    console.log(`Переключение на регион: ${data.region}`);
  });
  
  sdk.chat.on('error', (data) => {
    console.error('Ошибка:', data);
  });
  
  // Отправляем запрос с автоматическим переключением регионов при ошибках
  try {
    const response = await sdk.chat.chatWithRegionFailover(
      [{ role: 'user', content: 'Расскажи о квантовой физике' }],
      {
        model: 'claude-3-7-sonnet-20240229',
        thinking: true,
        // Порядок перебора регионов при ошибках
        regionPreference: ['us-east-1', 'eu-west-1', 'ap-southeast-2']
      }
    );
    
    console.log('Ответ получен из региона:', response.region);
    console.log('Ответ:', response.choices[0].message.content);
    
    return response;
  } catch (error) {
    console.error('Не удалось получить ответ ни из одного региона:', error);
    throw error;
  } finally {
    await sdk.chat.disconnectWebSocket();
  }
}

chatWithRegionalFailover().catch(console.error);
```

## Справочник всех событий WebSocket

Полный список всех поддерживаемых WebSocket событий, их описание, формат данных и примеры использования доступны в отдельном документе:

[Справочник WebSocket событий SDK](./WEBSOCKET_EVENTS.md)

В этом справочнике содержится подробная информация обо всех константах событий, их строковых значениях, форматах данных и рекомендациях по использованию в различных сценариях.