| | const express = require('express'); |
| | const crypto = require('crypto'); |
| | const router = express.Router(); |
| | const { browserClient } = require('../../../app/'); |
| | const { saveMessage, getConvoTitle, saveConvo, getConvo } = require('../../../models'); |
| | const { handleError, sendMessage, createOnProgress, handleText } = require('../../utils'); |
| | const { setHeaders } = require('../../middleware'); |
| |
|
| | router.post('/', setHeaders, async (req, res) => { |
| | const { |
| | endpoint, |
| | text, |
| | overrideParentMessageId = null, |
| | parentMessageId, |
| | conversationId: oldConversationId, |
| | } = req.body; |
| | if (text.length === 0) { |
| | return handleError(res, { text: 'Prompt empty or too short' }); |
| | } |
| | if (endpoint !== 'chatGPTBrowser') { |
| | return handleError(res, { text: 'Illegal request' }); |
| | } |
| |
|
| | |
| | const conversationId = oldConversationId || crypto.randomUUID(); |
| | const isNewConversation = !oldConversationId; |
| | const userMessageId = crypto.randomUUID(); |
| | const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000'; |
| | const userMessage = { |
| | messageId: userMessageId, |
| | sender: 'User', |
| | text, |
| | parentMessageId: userParentMessageId, |
| | conversationId, |
| | isCreatedByUser: true, |
| | }; |
| |
|
| | |
| | const endpointOption = { |
| | model: req.body?.model ?? 'text-davinci-002-render-sha', |
| | key: req.body?.key ?? null, |
| | }; |
| |
|
| | console.log('ask log', { |
| | userMessage, |
| | endpointOption, |
| | conversationId, |
| | }); |
| |
|
| | if (!overrideParentMessageId) { |
| | await saveMessage({ ...userMessage, user: req.user.id }); |
| | await saveConvo(req.user.id, { |
| | ...userMessage, |
| | ...endpointOption, |
| | conversationId, |
| | endpoint, |
| | }); |
| | } |
| |
|
| | |
| | return await ask({ |
| | isNewConversation, |
| | userMessage, |
| | endpointOption, |
| | conversationId, |
| | preSendRequest: true, |
| | overrideParentMessageId, |
| | req, |
| | res, |
| | }); |
| | }); |
| |
|
| | const ask = async ({ |
| | isNewConversation, |
| | userMessage, |
| | endpointOption, |
| | conversationId, |
| | overrideParentMessageId = null, |
| | req, |
| | res, |
| | }) => { |
| | let { text, parentMessageId: userParentMessageId, messageId: userMessageId } = userMessage; |
| | const user = req.user.id; |
| | let responseMessageId = crypto.randomUUID(); |
| | let getPartialMessage = null; |
| | try { |
| | let lastSavedTimestamp = 0; |
| | const { onProgress: progressCallback, getPartialText } = createOnProgress({ |
| | onProgress: ({ text }) => { |
| | const currentTimestamp = Date.now(); |
| | if (currentTimestamp - lastSavedTimestamp > 500) { |
| | lastSavedTimestamp = currentTimestamp; |
| | saveMessage({ |
| | messageId: responseMessageId, |
| | sender: endpointOption?.jailbreak ? 'Sydney' : 'BingAI', |
| | conversationId, |
| | parentMessageId: overrideParentMessageId || userMessageId, |
| | text: text, |
| | unfinished: true, |
| | cancelled: false, |
| | error: false, |
| | isCreatedByUser: false, |
| | user, |
| | }); |
| | } |
| | }, |
| | }); |
| |
|
| | getPartialMessage = getPartialText; |
| | const abortController = new AbortController(); |
| | let i = 0; |
| | let response = await browserClient({ |
| | text, |
| | parentMessageId: userParentMessageId, |
| | conversationId, |
| | ...endpointOption, |
| | abortController, |
| | userId: user, |
| | onProgress: progressCallback.call(null, { res, text }), |
| | onEventMessage: (eventMessage) => { |
| | let data = null; |
| | try { |
| | data = JSON.parse(eventMessage.data); |
| | } catch (e) { |
| | return; |
| | } |
| |
|
| | sendMessage(res, { |
| | message: { ...userMessage, conversationId: data.conversation_id }, |
| | created: i === 0, |
| | }); |
| |
|
| | if (i === 0) { |
| | i++; |
| | } |
| | }, |
| | }); |
| |
|
| | console.log('CLIENT RESPONSE', response); |
| |
|
| | const newConversationId = response.conversationId || conversationId; |
| | const newUserMassageId = response.parentMessageId || userMessageId; |
| | const newResponseMessageId = response.messageId; |
| |
|
| | |
| | response.text = response.response || '**ChatGPT refused to answer.**'; |
| |
|
| | let responseMessage = { |
| | conversationId: newConversationId, |
| | messageId: responseMessageId, |
| | newMessageId: newResponseMessageId, |
| | parentMessageId: overrideParentMessageId || newUserMassageId, |
| | text: await handleText(response), |
| | sender: endpointOption?.chatGptLabel || 'ChatGPT', |
| | unfinished: false, |
| | cancelled: false, |
| | error: false, |
| | isCreatedByUser: false, |
| | }; |
| |
|
| | await saveMessage({ ...responseMessage, user }); |
| | responseMessage.messageId = newResponseMessageId; |
| |
|
| | |
| |
|
| | |
| | let conversationUpdate = { conversationId: newConversationId, endpoint: 'chatGPTBrowser' }; |
| | if (conversationId != newConversationId) { |
| | if (isNewConversation) { |
| | |
| | conversationUpdate = { |
| | ...conversationUpdate, |
| | conversationId: conversationId, |
| | newConversationId: newConversationId, |
| | }; |
| | } else { |
| | |
| | conversationUpdate = { |
| | ...conversationUpdate, |
| | ...endpointOption, |
| | }; |
| | } |
| | } |
| |
|
| | await saveConvo(user, conversationUpdate); |
| | conversationId = newConversationId; |
| |
|
| | |
| | userMessage.conversationId = newConversationId; |
| | userMessage.messageId = newUserMassageId; |
| |
|
| | |
| | if (!overrideParentMessageId) { |
| | await saveMessage({ |
| | ...userMessage, |
| | user, |
| | messageId: userMessageId, |
| | newMessageId: newUserMassageId, |
| | }); |
| | } |
| | userMessageId = newUserMassageId; |
| |
|
| | sendMessage(res, { |
| | title: await getConvoTitle(user, conversationId), |
| | final: true, |
| | conversation: await getConvo(user, conversationId), |
| | requestMessage: userMessage, |
| | responseMessage: responseMessage, |
| | }); |
| | res.end(); |
| |
|
| | if (userParentMessageId == '00000000-0000-0000-0000-000000000000') { |
| | |
| | const title = await response.details.title; |
| | await saveConvo(user, { |
| | conversationId: conversationId, |
| | title, |
| | }); |
| | } |
| | } catch (error) { |
| | const errorMessage = { |
| | messageId: responseMessageId, |
| | sender: 'ChatGPT', |
| | conversationId, |
| | parentMessageId: overrideParentMessageId || userMessageId, |
| | unfinished: false, |
| | cancelled: false, |
| | error: true, |
| | isCreatedByUser: false, |
| | text: `${getPartialMessage() ?? ''}\n\nError message: "${error.message}"`, |
| | }; |
| | await saveMessage({ ...errorMessage, user }); |
| | handleError(res, errorMessage); |
| | } |
| | }; |
| |
|
| | module.exports = router; |
| |
|