Spaces:
Paused
Paused
| import { EventEmitter, WebSocket } from 'ws'; | |
| import { BaseMessage, AIMessage, HumanMessage } from '@langchain/core/messages'; | |
| import handleWebSearch from '../agents/webSearchAgent'; | |
| import handleAcademicSearch from '../agents/academicSearchAgent'; | |
| import handleWritingAssistant from '../agents/writingAssistant'; | |
| import handleWolframAlphaSearch from '../agents/wolframAlphaSearchAgent'; | |
| import handleYoutubeSearch from '../agents/youtubeSearchAgent'; | |
| import handleRedditSearch from '../agents/redditSearchAgent'; | |
| import type { BaseChatModel } from '@langchain/core/language_models/chat_models'; | |
| import type { Embeddings } from '@langchain/core/embeddings'; | |
| import logger from '../utils/logger'; | |
| type Message = { | |
| type: string; | |
| content: string; | |
| copilot: boolean; | |
| focusMode: string; | |
| history: Array<[string, string]>; | |
| }; | |
| const searchHandlers = { | |
| webSearch: handleWebSearch, | |
| academicSearch: handleAcademicSearch, | |
| writingAssistant: handleWritingAssistant, | |
| wolframAlphaSearch: handleWolframAlphaSearch, | |
| youtubeSearch: handleYoutubeSearch, | |
| redditSearch: handleRedditSearch, | |
| }; | |
| const handleEmitterEvents = ( | |
| emitter: EventEmitter, | |
| ws: WebSocket, | |
| id: string, | |
| ) => { | |
| emitter.on('data', (data) => { | |
| const parsedData = JSON.parse(data); | |
| if (parsedData.type === 'response') { | |
| ws.send( | |
| JSON.stringify({ | |
| type: 'message', | |
| data: parsedData.data, | |
| messageId: id, | |
| }), | |
| ); | |
| } else if (parsedData.type === 'sources') { | |
| ws.send( | |
| JSON.stringify({ | |
| type: 'sources', | |
| data: parsedData.data, | |
| messageId: id, | |
| }), | |
| ); | |
| } | |
| }); | |
| emitter.on('end', () => { | |
| ws.send(JSON.stringify({ type: 'messageEnd', messageId: id })); | |
| }); | |
| emitter.on('error', (data) => { | |
| const parsedData = JSON.parse(data); | |
| ws.send(JSON.stringify({ type: 'error', data: parsedData.data })); | |
| }); | |
| }; | |
| export const handleMessage = async ( | |
| message: string, | |
| ws: WebSocket, | |
| llm: BaseChatModel, | |
| embeddings: Embeddings, | |
| ) => { | |
| try { | |
| const parsedMessage = JSON.parse(message) as Message; | |
| const id = Math.random().toString(36).substring(7); | |
| if (!parsedMessage.content) | |
| return ws.send( | |
| JSON.stringify({ type: 'error', data: 'Invalid message format' }), | |
| ); | |
| const history: BaseMessage[] = parsedMessage.history.map((msg) => { | |
| if (msg[0] === 'human') { | |
| return new HumanMessage({ | |
| content: msg[1], | |
| }); | |
| } else { | |
| return new AIMessage({ | |
| content: msg[1], | |
| }); | |
| } | |
| }); | |
| if (parsedMessage.type === 'message') { | |
| const handler = searchHandlers[parsedMessage.focusMode]; | |
| if (handler) { | |
| const emitter = handler( | |
| parsedMessage.content, | |
| history, | |
| llm, | |
| embeddings, | |
| ); | |
| handleEmitterEvents(emitter, ws, id); | |
| } else { | |
| ws.send(JSON.stringify({ type: 'error', data: 'Invalid focus mode' })); | |
| } | |
| } | |
| } catch (err) { | |
| ws.send(JSON.stringify({ type: 'error', data: 'Invalid message format' })); | |
| logger.error(`Failed to handle message: ${err}`); | |
| } | |
| }; | |