UNPKG

solver-sdk

Version:

SDK для интеграции с Code Solver Backend API

211 lines 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setupSocketEventHandlers = setupSocketEventHandlers; exports.generateId = generateId; exports.createWebSocketEventHandler = createWebSocketEventHandler; exports.normalizeEventName = normalizeEventName; const websocket_events_constants_1 = require("../../constants/websocket-events.constants"); /** * Настраивает обработчики событий для WebSocket */ function setupSocketEventHandlers(socket, socketId, sessionId, onEvent) { // Установка обработчиков событий socket.on('connect', () => { console.log(`[SDK] WebSocket подключен: ${socket.id}, задано socketId: ${socketId}`); // При подключении отправляем событие аутентификации socket.emit('authenticate', { socketId: socketId, token: 'test-token' }); // Отправляем событие присоединения к комнате с ID сессии socket.emit('join_room', { roomId: sessionId }); // Вызываем обработчик события connect if (onEvent) { onEvent('connect', { socketId }); } }); // Обработчик сообщений от сервера socket.on('message', (data) => { if (!onEvent || !data) return; // Обрабатываем случай, когда сервер отправляет сообщения в формате JSON-строки if (typeof data === 'string') { try { data = JSON.parse(data); } catch (e) { // Оставляем как строку, если не удалось распарсить } } // Передаем событие напрямую, без преобразования формата if (data && data.type) { onEvent(data.type, data); } else { // Передаем все остальные сообщения как есть onEvent('message', data); } }); // Обработчик ошибок socket.on('error', (error) => { console.error('[SDK] WebSocket error:', error); // Проверяем наличие ошибки географических ограничений const isGeoRestriction = (error.type === 'geo_restriction' || error.code === 403) && error.message && (error.message.includes('ограничен в вашем регионе') || error.message.includes('Request not allowed')); if (isGeoRestriction) { console.error('\n=============================================='); console.error('⚠️ ОШИБКА ГЕОГРАФИЧЕСКОГО ОГРАНИЧЕНИЯ API ANTHROPIC'); console.error('⚠️ Для работы с API Anthropic требуется VPN или прокси'); console.error('⚠️ Anthropic API доступен только из определенных регионов'); console.error('=============================================='); } if (onEvent) { onEvent('error', { message: error.message || 'Unknown WebSocket error', code: error.code, type: isGeoRestriction ? 'geo_restriction' : (error.type || 'websocket_error') }); } }); // Обработчик отключения socket.on('disconnect', (reason) => { console.log(`[SDK] WebSocket отключен: ${reason}`); if (onEvent) { onEvent('disconnect', { reason }); } }); // Обработчики для событий аутентификации socket.on('authenticated', (data) => { console.log('[SDK] Аутентификация успешна', data); if (onEvent) { onEvent('authenticated', data); } }); socket.on('authentication_error', (data) => { console.error('[SDK] Ошибка аутентификации:', data); if (onEvent) { onEvent('error', { message: 'Ошибка аутентификации: ' + (data.message || 'Unknown error'), code: 'AUTH_ERROR' }); } }); // Список актуальных событий API Anthropic [ 'message_start', 'content_block_start', 'content_block_delta', 'content_block_stop', 'message_delta', 'message_stop', 'done', 'ping' ].forEach(eventType => { socket.on(eventType, (data) => { if (!onEvent) return; // Передаем события в их исходном формате без преобразования onEvent(eventType, data); }); }); } /** * Генерирует случайный ID указанной длины */ function generateId(length) { const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } /** * Создает обработчик WebSocket событий для работы с API Anthropic * @param socket Socket.io сокет * @param options Опции обработчика * @returns Функция отписки от событий */ function createWebSocketEventHandler(socket, options) { const { onMessageStart, onContentBlockStart, onContentBlockDelta, onContentBlockStop, onMessageDelta, onMessageStop, onThinking, onText, onInputJson, onSignature, onError, onDone } = options; // Общая функция для обработки events const handleEvent = (event, handler) => { if (handler) { socket.on(event, (data) => { try { handler(data); } catch (err) { console.error(`Ошибка при обработке события ${event}:`, err); if (onError) onError(err); } }); } }; // Регистрируем обработчики для всех требуемых событий handleEvent(websocket_events_constants_1.WebSocketEvents.MESSAGE_START, onMessageStart); handleEvent(websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_START, onContentBlockStart); handleEvent(websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_STOP, onContentBlockStop); handleEvent(websocket_events_constants_1.WebSocketEvents.MESSAGE_DELTA, onMessageDelta); handleEvent(websocket_events_constants_1.WebSocketEvents.MESSAGE_STOP, onMessageStop); handleEvent(websocket_events_constants_1.WebSocketEvents.ERROR, onError); handleEvent(websocket_events_constants_1.WebSocketEvents.DONE, onDone); // Обработчик дельт блоков контента if (onContentBlockDelta || onThinking || onText || onInputJson || onSignature) { socket.on(websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_DELTA, (data) => { try { // Вызываем общий обработчик для всех дельт if (onContentBlockDelta) { onContentBlockDelta(data); } // Обрабатываем разные типы дельт if (data.delta && data.delta.type) { // Обработка thinking if (data.delta.type === websocket_events_constants_1.ContentBlockDeltaTypes.THINKING_DELTA && onThinking && data.delta.thinking) { onThinking(data.delta.thinking); } // Обработка текста else if (data.delta.type === websocket_events_constants_1.ContentBlockDeltaTypes.TEXT_DELTA && onText && data.delta.text) { onText(data.delta.text); } // Обработка JSON для инструментов else if (data.delta.type === websocket_events_constants_1.ContentBlockDeltaTypes.INPUT_JSON_DELTA && onInputJson) { const jsonData = data.delta.input_json || ''; onInputJson(jsonData); } // Обработка подписи для верификации else if (data.delta.type === websocket_events_constants_1.ContentBlockDeltaTypes.SIGNATURE_DELTA && onSignature && data.delta.signature) { onSignature(data.delta.signature); } } } catch (err) { console.error('Ошибка при обработке события content_block_delta:', err); if (onError) onError(err); } }); } // Возвращаем функцию для отписки от всех событий return () => { socket.off(websocket_events_constants_1.WebSocketEvents.MESSAGE_START); socket.off(websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_START); socket.off(websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_DELTA); socket.off(websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_STOP); socket.off(websocket_events_constants_1.WebSocketEvents.MESSAGE_DELTA); socket.off(websocket_events_constants_1.WebSocketEvents.MESSAGE_STOP); socket.off(websocket_events_constants_1.WebSocketEvents.ERROR); socket.off(websocket_events_constants_1.WebSocketEvents.DONE); }; } /** * Нормализует имя события для совместимости с API Anthropic * @param eventName Имя события * @returns Нормализованное имя события */ function normalizeEventName(eventName) { const eventMap = { 'message.start': websocket_events_constants_1.WebSocketEvents.MESSAGE_START, 'message.stop': websocket_events_constants_1.WebSocketEvents.MESSAGE_STOP, 'message.delta': websocket_events_constants_1.WebSocketEvents.MESSAGE_DELTA, 'content_block.start': websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_START, 'content_block.delta': websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_DELTA, 'content_block.stop': websocket_events_constants_1.WebSocketEvents.CONTENT_BLOCK_STOP, }; return eventMap[eventName] || eventName; } //# sourceMappingURL=websocket-helpers.js.map