232 lines
7.6 KiB
TypeScript
232 lines
7.6 KiB
TypeScript
import { 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';
|
|
|
|
type Message = {
|
|
type: string;
|
|
content: string;
|
|
copilot: boolean;
|
|
focusMode: string;
|
|
history: Array<[string, string]>;
|
|
};
|
|
|
|
export const handleMessage = async (message: string, ws: WebSocket) => {
|
|
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') {
|
|
switch (parsedMessage.focusMode) {
|
|
case 'webSearch': {
|
|
const emitter = handleWebSearch(parsedMessage.content, history);
|
|
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 }));
|
|
});
|
|
break;
|
|
}
|
|
case 'academicSearch': {
|
|
const emitter = handleAcademicSearch(parsedMessage.content, history);
|
|
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 }));
|
|
});
|
|
break;
|
|
}
|
|
case 'writingAssistant': {
|
|
const emitter = handleWritingAssistant(
|
|
parsedMessage.content,
|
|
history,
|
|
);
|
|
emitter.on('data', (data) => {
|
|
const parsedData = JSON.parse(data);
|
|
if (parsedData.type === 'response') {
|
|
ws.send(
|
|
JSON.stringify({
|
|
type: 'message',
|
|
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 }));
|
|
});
|
|
break;
|
|
}
|
|
case 'wolframAlphaSearch': {
|
|
const emitter = handleWolframAlphaSearch(
|
|
parsedMessage.content,
|
|
history,
|
|
);
|
|
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 }));
|
|
});
|
|
break;
|
|
}
|
|
case 'youtubeSearch': {
|
|
const emitter = handleYoutubeSearch(parsedMessage.content, history);
|
|
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 }));
|
|
});
|
|
break;
|
|
}
|
|
case 'redditSearch': {
|
|
const emitter = handleRedditSearch(parsedMessage.content, history);
|
|
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 }));
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to handle message', error);
|
|
ws.send(JSON.stringify({ type: 'error', data: 'Invalid message format' }));
|
|
}
|
|
};
|