solver-sdk
Version:
SDK для интеграции с Code Solver Backend API
211 lines • 10.9 kB
JavaScript
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
;