Spaces:
Running
Running
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}`); | |
} | |
}; | |