mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-06 02:28:51 +01:00
Build/Refactor: lint pre-commit hook and reformat repo to spec (#314)
* build/refactor: move lint/prettier packages to project root, install husky, add pre-commit hook * refactor: reformat files * build: put full eslintrc back with all rules
This commit is contained in:
parent
8d75b25104
commit
7fdc862042
157 changed files with 4836 additions and 2403 deletions
|
|
@ -1,39 +0,0 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: ['eslint:recommended'],
|
||||
overrides: [],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
rules: {
|
||||
indent: ['error', 2, { SwitchCase: 1 }],
|
||||
'max-len': [
|
||||
'error',
|
||||
{
|
||||
code: 150,
|
||||
ignoreStrings: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
ignoreComments: true
|
||||
}
|
||||
],
|
||||
'linebreak-style': 0,
|
||||
'arrow-parens': [2, 'as-needed', { requireForBlockBody: true }],
|
||||
// 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
|
||||
'no-console': 'off',
|
||||
'import/extensions': 'off',
|
||||
'no-use-before-define': [
|
||||
'error',
|
||||
{
|
||||
functions: false
|
||||
}
|
||||
],
|
||||
'no-promise-executor-return': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'no-continue': 'off',
|
||||
'no-restricted-syntax': 'off'
|
||||
}
|
||||
};
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true,
|
||||
"endOfLine": "lf",
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"insertPragma": false,
|
||||
"singleAttributePerLine": true,
|
||||
"bracketSameLine": false,
|
||||
"jsxBracketSameLine": false,
|
||||
"jsxSingleQuote": false,
|
||||
"printWidth": 110,
|
||||
"proseWrap": "preserve",
|
||||
"quoteProps": "as-needed",
|
||||
"requirePragma": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "none",
|
||||
"useTabs": false,
|
||||
"vueIndentScriptAndStyle": false,
|
||||
"parser": "babel"
|
||||
}
|
||||
|
|
@ -23,7 +23,8 @@ const askBing = async ({
|
|||
|
||||
const bingAIClient = new BingAIClient({
|
||||
// "_U" cookie from bing.com
|
||||
userToken: process.env.BINGAI_TOKEN == 'user_provided' ? token : process.env.BINGAI_TOKEN ?? null,
|
||||
userToken:
|
||||
process.env.BINGAI_TOKEN == 'user_provided' ? token : process.env.BINGAI_TOKEN ?? null,
|
||||
// If the above doesn't work, provide all your cookies as a string instead
|
||||
// cookies: '',
|
||||
debug: false,
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ const browserClient = async ({
|
|||
|
||||
const clientOptions = {
|
||||
// Warning: This will expose your access token to a third party. Consider the risks before using this.
|
||||
reverseProxyUrl: process.env.CHATGPT_REVERSE_PROXY || 'https://ai.fakeopen.com/api/conversation',
|
||||
reverseProxyUrl:
|
||||
process.env.CHATGPT_REVERSE_PROXY || 'https://ai.fakeopen.com/api/conversation',
|
||||
// Access token from https://chat.openai.com/api/auth/session
|
||||
accessToken: process.env.CHATGPT_TOKEN == 'user_provided' ? token : process.env.CHATGPT_TOKEN ?? null,
|
||||
accessToken:
|
||||
process.env.CHATGPT_TOKEN == 'user_provided' ? token : process.env.CHATGPT_TOKEN ?? null,
|
||||
model: model,
|
||||
debug: false,
|
||||
proxy: process.env.PROXY || null,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
require('dotenv').config();
|
||||
const { KeyvFile } = require('keyv-file');
|
||||
const { genAzureEndpoint } = require('../../utils/genAzureEndpoints');
|
||||
const tiktoken = require("@dqbd/tiktoken");
|
||||
const tiktoken = require('@dqbd/tiktoken');
|
||||
const encoding_for_model = tiktoken.encoding_for_model;
|
||||
|
||||
const askClient = async ({
|
||||
|
|
@ -27,7 +27,7 @@ const askClient = async ({
|
|||
|
||||
const azure = process.env.AZURE_OPENAI_API_KEY ? true : false;
|
||||
if (promptPrefix == null) {
|
||||
promptText = "You are ChatGPT, a large language model trained by OpenAI.";
|
||||
promptText = 'You are ChatGPT, a large language model trained by OpenAI.';
|
||||
} else {
|
||||
promptText = promptPrefix;
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ const askClient = async ({
|
|||
},
|
||||
chatGptLabel,
|
||||
promptPrefix,
|
||||
proxy: process.env.PROXY || null,
|
||||
proxy: process.env.PROXY || null
|
||||
// debug: true
|
||||
};
|
||||
|
||||
|
|
@ -77,16 +77,16 @@ const askClient = async ({
|
|||
const res = await client.sendMessage(text, { ...options, userId });
|
||||
// return res;
|
||||
// create a new response object that includes the token counts
|
||||
const newRes = {
|
||||
...res,
|
||||
usage: {
|
||||
prompt_tokens: prompt_tokens.length,
|
||||
completion_tokens: text_tokens.length,
|
||||
total_tokens: prompt_tokens.length + text_tokens.length
|
||||
}
|
||||
};
|
||||
const newRes = {
|
||||
...res,
|
||||
usage: {
|
||||
prompt_tokens: prompt_tokens.length,
|
||||
completion_tokens: text_tokens.length,
|
||||
total_tokens: prompt_tokens.length + text_tokens.length
|
||||
}
|
||||
};
|
||||
|
||||
return newRes;
|
||||
return newRes;
|
||||
};
|
||||
|
||||
module.exports = { askClient };
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ const TextStream = require('../stream');
|
|||
const { google } = require('googleapis');
|
||||
const { Agent, ProxyAgent } = require('undici');
|
||||
const { getMessages, saveMessage, saveConvo } = require('../../models');
|
||||
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('@dqbd/tiktoken');
|
||||
const {
|
||||
encoding_for_model: encodingForModel,
|
||||
get_encoding: getEncoding
|
||||
} = require('@dqbd/tiktoken');
|
||||
|
||||
const tokenizersCache = {};
|
||||
|
||||
|
|
@ -65,7 +68,8 @@ class GoogleAgent {
|
|||
// The max prompt tokens is determined by the max context tokens minus the max response tokens.
|
||||
// Earlier messages will be dropped until the prompt is within the limit.
|
||||
this.maxResponseTokens = this.modelOptions.maxOutputTokens || 1024;
|
||||
this.maxPromptTokens = this.options.maxPromptTokens || this.maxContextTokens - this.maxResponseTokens;
|
||||
this.maxPromptTokens =
|
||||
this.options.maxPromptTokens || this.maxContextTokens - this.maxResponseTokens;
|
||||
|
||||
if (this.maxPromptTokens + this.maxResponseTokens > this.maxContextTokens) {
|
||||
throw new Error(
|
||||
|
|
@ -291,7 +295,10 @@ class GoogleAgent {
|
|||
try {
|
||||
const result = await this.getCompletion(message, messages, opts.abortController);
|
||||
blocked = result?.predictions?.[0]?.safetyAttributes?.blocked;
|
||||
reply = result?.predictions?.[0]?.candidates?.[0]?.content || result?.predictions?.[0]?.content || '';
|
||||
reply =
|
||||
result?.predictions?.[0]?.candidates?.[0]?.content ||
|
||||
result?.predictions?.[0]?.content ||
|
||||
'';
|
||||
if (blocked === true) {
|
||||
reply = `Google blocked a proper response to your message:\n${JSON.stringify(
|
||||
result.predictions[0].safetyAttributes
|
||||
|
|
|
|||
|
|
@ -16,10 +16,7 @@ class TextStream extends Readable {
|
|||
if (this.currentIndex < this.text.length) {
|
||||
setTimeout(() => {
|
||||
const remainingChars = this.text.length - this.currentIndex;
|
||||
const chunkSize = Math.min(
|
||||
this.randomInt(minChunkSize, maxChunkSize + 1),
|
||||
remainingChars
|
||||
);
|
||||
const chunkSize = Math.min(this.randomInt(minChunkSize, maxChunkSize + 1), remainingChars);
|
||||
|
||||
const chunk = this.text.slice(this.currentIndex, this.currentIndex + chunkSize);
|
||||
this.push(chunk);
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ const getCitations = (res) => {
|
|||
if (!textBlocks) return '';
|
||||
let links = textBlocks[textBlocks.length - 1]?.text.match(regex);
|
||||
if (links?.length === 0 || !links) return '';
|
||||
links = links.map((link) => link.trim());
|
||||
links = links.map(link => link.trim());
|
||||
return links.join('\n');
|
||||
};
|
||||
|
||||
module.exports = getCitations;
|
||||
module.exports = getCitations;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ function mergeSort(arr, compareFn) {
|
|||
if (arr.length <= 1) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
const mid = Math.floor(arr.length / 2);
|
||||
const leftArr = arr.slice(0, mid);
|
||||
const rightArr = arr.slice(mid);
|
||||
|
||||
|
||||
return merge(mergeSort(leftArr, compareFn), mergeSort(rightArr, compareFn), compareFn);
|
||||
}
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ function merge(leftArr, rightArr, compareFn) {
|
|||
const result = [];
|
||||
let leftIndex = 0;
|
||||
let rightIndex = 0;
|
||||
|
||||
|
||||
while (leftIndex < leftArr.length && rightIndex < rightArr.length) {
|
||||
if (compareFn(leftArr[leftIndex], rightArr[rightIndex]) < 0) {
|
||||
result.push(leftArr[leftIndex++]);
|
||||
|
|
@ -22,8 +22,8 @@ function merge(leftArr, rightArr, compareFn) {
|
|||
result.push(rightArr[rightIndex++]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result.concat(leftArr.slice(leftIndex)).concat(rightArr.slice(rightIndex));
|
||||
}
|
||||
|
||||
module.exports = mergeSort;
|
||||
module.exports = mergeSort;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const requireLocalAuth = (req, res, next) => {
|
|||
}
|
||||
if (!user) {
|
||||
log({
|
||||
title: '(requireLocalAuth) Error: No user',
|
||||
title: '(requireLocalAuth) Error: No user'
|
||||
});
|
||||
return res.status(422).send(info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const Message = require('./schema/messageSchema');
|
|||
|
||||
module.exports = {
|
||||
Message,
|
||||
|
||||
|
||||
async saveMessage({
|
||||
messageId,
|
||||
newMessageId,
|
||||
|
|
@ -32,7 +32,7 @@ module.exports = {
|
|||
},
|
||||
{ upsert: true, new: true }
|
||||
);
|
||||
|
||||
|
||||
return {
|
||||
messageId,
|
||||
conversationId,
|
||||
|
|
@ -41,13 +41,12 @@ module.exports = {
|
|||
text,
|
||||
isCreatedByUser
|
||||
};
|
||||
|
||||
} catch (err) {
|
||||
console.error(`Error saving message: ${err}`);
|
||||
throw new Error('Failed to save message.');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async deleteMessagesSince({ messageId, conversationId }) {
|
||||
try {
|
||||
const message = await Message.findOne({ messageId }).exec();
|
||||
|
|
@ -57,27 +56,24 @@ module.exports = {
|
|||
.deleteMany({ createdAt: { $gt: message.createdAt } })
|
||||
.exec();
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error(`Error deleting messages: ${err}`);
|
||||
throw new Error('Failed to delete messages.');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async getMessages(filter) {
|
||||
try {
|
||||
return await Message.find(filter).sort({ createdAt: 1 }).exec();
|
||||
|
||||
} catch (err) {
|
||||
console.error(`Error getting messages: ${err}`);
|
||||
throw new Error('Failed to get messages.');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async deleteMessages(filter) {
|
||||
try {
|
||||
return await Message.deleteMany(filter).exec();
|
||||
|
||||
} catch (err) {
|
||||
console.error(`Error deleting messages: ${err}`);
|
||||
throw new Error('Failed to delete messages.');
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
const mongoose = require('mongoose');
|
||||
|
||||
const promptSchema = mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
const promptSchema = mongoose.Schema(
|
||||
{
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
prompt: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
category: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
prompt: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
},
|
||||
}, { timestamps: true });
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
const Prompt = mongoose.models.Prompt || mongoose.model('Prompt', promptSchema);
|
||||
|
||||
|
|
@ -31,7 +34,7 @@ module.exports = {
|
|||
},
|
||||
getPrompts: async (filter) => {
|
||||
try {
|
||||
return await Prompt.find(filter).exec()
|
||||
return await Prompt.find(filter).exec();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return { prompt: 'Error getting prompts' };
|
||||
|
|
@ -39,10 +42,10 @@ module.exports = {
|
|||
},
|
||||
deletePrompts: async (filter) => {
|
||||
try {
|
||||
return await Prompt.deleteMany(filter).exec()
|
||||
return await Prompt.deleteMany(filter).exec();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return { prompt: 'Error deleting prompts' };
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ userSchema.methods.comparePassword = function (candidatePassword, callback) {
|
|||
};
|
||||
|
||||
module.exports.hashPassword = async (password) => {
|
||||
|
||||
const hashedPassword = await new Promise((resolve, reject) => {
|
||||
bcrypt.hash(password, 10, function (err, hash) {
|
||||
if (err) reject(err);
|
||||
|
|
|
|||
|
|
@ -19,10 +19,7 @@ const createMeiliMongooseModel = function ({ index, indexName, client, attribute
|
|||
static async clearMeiliIndex() {
|
||||
await index.delete();
|
||||
// await index.deleteAllDocuments();
|
||||
await this.collection.updateMany(
|
||||
{ _meiliIndex: true },
|
||||
{ $set: { _meiliIndex: false } }
|
||||
);
|
||||
await this.collection.updateMany({ _meiliIndex: true }, { $set: { _meiliIndex: false } });
|
||||
}
|
||||
|
||||
static async resetIndex() {
|
||||
|
|
@ -67,7 +64,7 @@ const createMeiliMongooseModel = function ({ index, indexName, client, attribute
|
|||
return { ...results, [key]: 1 };
|
||||
},
|
||||
{ _id: 1 }
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Add additional data from mongodb into Meili search hits
|
||||
|
|
@ -198,8 +195,8 @@ module.exports = function mongoMeili(schema, options) {
|
|||
if (Object.prototype.hasOwnProperty.call(schema.obj, 'messages')) {
|
||||
console.log('Syncing convos...');
|
||||
mongoose.model('Conversation').syncWithMeili();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(schema.obj, 'messageId')) {
|
||||
console.log('Syncing messages...');
|
||||
mongoose.model('Message').syncWithMeili();
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
const mongoose = require("mongoose");
|
||||
const mongoose = require('mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const tokenSchema = new Schema({
|
||||
userId: {
|
||||
type: Schema.Types.ObjectId,
|
||||
required: true,
|
||||
ref: "user",
|
||||
ref: 'user'
|
||||
},
|
||||
token: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
createdAt: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: Date.now,
|
||||
expires: 900,
|
||||
},
|
||||
expires: 900
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model("Token", tokenSchema);
|
||||
module.exports = mongoose.model('Token', tokenSchema);
|
||||
|
|
|
|||
|
|
@ -3,28 +3,26 @@ const {
|
|||
logoutUser,
|
||||
registerUser,
|
||||
requestPasswordReset,
|
||||
resetPassword,
|
||||
} = require("../services/auth.service");
|
||||
resetPassword
|
||||
} = require('../services/auth.service');
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
const loginController = async (req, res) => {
|
||||
try {
|
||||
const token = req.user.generateToken();
|
||||
const user = await loginUser(req.user)
|
||||
if(user) {
|
||||
const user = await loginUser(req.user);
|
||||
if (user) {
|
||||
res.cookie('token', token, {
|
||||
expires: new Date(Date.now() + eval(process.env.SESSION_EXPIRY)),
|
||||
httpOnly: false,
|
||||
secure: isProduction
|
||||
});
|
||||
res.status(200).send({ token, user });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return res.status(400).json({ message: 'Invalid credentials' });
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return res.status(500).json({ message: err.message });
|
||||
}
|
||||
|
|
@ -35,22 +33,20 @@ const logoutController = async (req, res) => {
|
|||
const { refreshToken } = signedCookies;
|
||||
try {
|
||||
const logout = await logoutUser(req.user, refreshToken);
|
||||
console.log(logout)
|
||||
console.log(logout);
|
||||
const { status, message } = logout;
|
||||
if (status === 200) {
|
||||
res.clearCookie('token');
|
||||
res.clearCookie('refreshToken');
|
||||
res.status(status).send({ message });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.status(status).send({ message });
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return res.status(500).json({ message: err.message });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const registrationController = async (req, res) => {
|
||||
try {
|
||||
|
|
@ -65,13 +61,11 @@ const registrationController = async (req, res) => {
|
|||
secure: isProduction
|
||||
});
|
||||
res.status(status).send({ user });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const { status, message } = response;
|
||||
res.status(status).send({ message });
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return res.status(500).json({ message: err.message });
|
||||
}
|
||||
|
|
@ -83,17 +77,13 @@ const getUserController = async (req, res) => {
|
|||
|
||||
const resetPasswordRequestController = async (req, res) => {
|
||||
try {
|
||||
const resetService = await requestPasswordReset(
|
||||
req.body.email
|
||||
);
|
||||
const resetService = await requestPasswordReset(req.body.email);
|
||||
if (resetService.link) {
|
||||
return res.status(200).json(resetService);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return res.status(400).json(resetService);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return res.status(400).json({ message: e.message });
|
||||
}
|
||||
|
|
@ -106,14 +96,12 @@ const resetPasswordController = async (req, res) => {
|
|||
req.body.token,
|
||||
req.body.password
|
||||
);
|
||||
if(resetPasswordService instanceof Error) {
|
||||
if (resetPasswordService instanceof Error) {
|
||||
return res.status(400).json(resetPasswordService);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return res.status(200).json(resetPasswordService);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return res.status(400).json({ message: e.message });
|
||||
}
|
||||
|
|
@ -176,5 +164,5 @@ module.exports = {
|
|||
refreshController,
|
||||
registrationController,
|
||||
resetPasswordRequestController,
|
||||
resetPasswordController,
|
||||
};
|
||||
resetPasswordController
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ const projectPath = path.join(__dirname, '..', '..', 'client');
|
|||
app.use(passport.initialize());
|
||||
require('../strategies/jwtStrategy');
|
||||
require('../strategies/localStrategy');
|
||||
if(process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
|
||||
if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
|
||||
require('../strategies/googleStrategy');
|
||||
}
|
||||
if(process.env.FACEBOOK_CLIENT_ID && process.env.FACEBOOK_CLIENT_SECRET) {
|
||||
if (process.env.FACEBOOK_CLIENT_ID && process.env.FACEBOOK_CLIENT_SECRET) {
|
||||
require('../strategies/facebookStrategy');
|
||||
}
|
||||
app.use('/oauth', routes.oauth)
|
||||
app.use('/oauth', routes.oauth);
|
||||
// api endpoint
|
||||
app.use('/api/auth', routes.auth);
|
||||
app.use('/api/search', routes.search);
|
||||
|
|
@ -48,8 +48,6 @@ const projectPath = path.join(__dirname, '..', '..', 'client');
|
|||
app.use('/api/tokenizer', routes.tokenizer);
|
||||
app.use('/api/endpoints', routes.endpoints);
|
||||
|
||||
|
||||
|
||||
// static files
|
||||
app.get('/*', function (req, res) {
|
||||
res.sendFile(path.join(projectPath, 'dist', 'index.html'));
|
||||
|
|
@ -60,7 +58,8 @@ const projectPath = path.join(__dirname, '..', '..', 'client');
|
|||
console.log(
|
||||
`Server listening on all interface at port ${port}. Use http://localhost:${port} to access it`
|
||||
);
|
||||
else console.log(`Server listening at http://${host == '0.0.0.0' ? 'localhost' : host}:${port}`);
|
||||
else
|
||||
console.log(`Server listening at http://${host == '0.0.0.0' ? 'localhost' : host}:${port}`);
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
|||
|
|
@ -147,11 +147,13 @@ const ask = async ({
|
|||
const newConversationId = endpointOption?.jailbreak
|
||||
? response.jailbreakConversationId
|
||||
: response.conversationId || conversationId;
|
||||
const newUserMassageId = response.parentMessageId || response.details.requestId || userMessageId;
|
||||
const newUserMassageId =
|
||||
response.parentMessageId || response.details.requestId || userMessageId;
|
||||
const newResponseMessageId = response.messageId || response.details.messageId;
|
||||
|
||||
// STEP1 generate response message
|
||||
response.text = response.response || response.details.spokenText || '**Bing refused to answer.**';
|
||||
response.text =
|
||||
response.response || response.details.spokenText || '**Bing refused to answer.**';
|
||||
|
||||
let responseMessage = {
|
||||
conversationId: newConversationId,
|
||||
|
|
@ -161,7 +163,8 @@ const ask = async ({
|
|||
sender: endpointOption?.jailbreak ? 'Sydney' : 'BingAI',
|
||||
text: await handleText(response, true),
|
||||
suggestions:
|
||||
response.details.suggestedResponses && response.details.suggestedResponses.map((s) => s.text),
|
||||
response.details.suggestedResponses &&
|
||||
response.details.suggestedResponses.map(s => s.text),
|
||||
unfinished: false,
|
||||
cancelled: false,
|
||||
error: false
|
||||
|
|
@ -215,7 +218,11 @@ const ask = async ({
|
|||
|
||||
// If response has parentMessageId, the fake userMessage.messageId should be updated to the real one.
|
||||
if (!overrideParentMessageId)
|
||||
await saveMessage({ ...userMessage, messageId: userMessageId, newMessageId: newUserMassageId });
|
||||
await saveMessage({
|
||||
...userMessage,
|
||||
messageId: userMessageId,
|
||||
newMessageId: newUserMassageId
|
||||
});
|
||||
userMessageId = newUserMassageId;
|
||||
|
||||
sendMessage(res, {
|
||||
|
|
@ -228,7 +235,11 @@ const ask = async ({
|
|||
res.end();
|
||||
|
||||
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
|
||||
const title = await titleConvo({ endpoint: endpointOption?.endpoint, text, response: responseMessage });
|
||||
const title = await titleConvo({
|
||||
endpoint: endpointOption?.endpoint,
|
||||
text,
|
||||
response: responseMessage
|
||||
});
|
||||
|
||||
await saveConvo(req.user.id, {
|
||||
conversationId: conversationId,
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ router.post('/', requireJwtAuth, async (req, res) => {
|
|||
};
|
||||
|
||||
const availableModels = getChatGPTBrowserModels();
|
||||
if (availableModels.find((model) => model === endpointOption.model) === undefined)
|
||||
if (availableModels.find(model => model === endpointOption.model) === undefined)
|
||||
return handleError(res, { text: 'Illegal request: model' });
|
||||
|
||||
console.log('ask log', {
|
||||
|
|
@ -180,7 +180,11 @@ const ask = async ({
|
|||
|
||||
// If response has parentMessageId, the fake userMessage.messageId should be updated to the real one.
|
||||
if (!overrideParentMessageId)
|
||||
await saveMessage({ ...userMessage, messageId: userMessageId, newMessageId: newUserMassageId });
|
||||
await saveMessage({
|
||||
...userMessage,
|
||||
messageId: userMessageId,
|
||||
newMessageId: newUserMassageId
|
||||
});
|
||||
userMessageId = newUserMassageId;
|
||||
|
||||
sendMessage(res, {
|
||||
|
|
|
|||
|
|
@ -238,7 +238,11 @@ const ask = async ({
|
|||
|
||||
// If response has parentMessageId, the fake userMessage.messageId should be updated to the real one.
|
||||
if (!overrideParentMessageId)
|
||||
await saveMessage({ ...userMessage, messageId: userMessageId, newMessageId: newUserMassageId });
|
||||
await saveMessage({
|
||||
...userMessage,
|
||||
messageId: userMessageId,
|
||||
newMessageId: newUserMassageId
|
||||
});
|
||||
userMessageId = newUserMassageId;
|
||||
|
||||
sendMessage(res, {
|
||||
|
|
@ -251,7 +255,12 @@ const ask = async ({
|
|||
res.end();
|
||||
|
||||
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
|
||||
const title = await titleConvo({ endpoint: endpointOption?.endpoint, text, response: responseMessage, oaiApiKey });
|
||||
const title = await titleConvo({
|
||||
endpoint: endpointOption?.endpoint,
|
||||
text,
|
||||
response: responseMessage,
|
||||
oaiApiKey
|
||||
});
|
||||
await saveConvo(req.user.id, {
|
||||
conversationId: conversationId,
|
||||
title
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const {
|
|||
loginController,
|
||||
logoutController,
|
||||
refreshController,
|
||||
registrationController,
|
||||
registrationController
|
||||
} = require('../controllers/auth.controller');
|
||||
const requireJwtAuth = require('../../middleware/requireJwtAuth');
|
||||
const requireLocalAuth = require('../../middleware/requireLocalAuth');
|
||||
|
|
|
|||
|
|
@ -36,13 +36,14 @@ router.get('/', async function (req, res) {
|
|||
}
|
||||
|
||||
const google =
|
||||
key || palmUser ? { userProvide: palmUser, availableModels: ['chat-bison', 'text-bison'] } : false;
|
||||
key || palmUser
|
||||
? { userProvide: palmUser, availableModels: ['chat-bison', 'text-bison'] }
|
||||
: false;
|
||||
const azureOpenAI = !!process.env.AZURE_OPENAI_KEY;
|
||||
const apiKey = process.env.OPENAI_KEY || process.env.AZURE_OPENAI_API_KEY;
|
||||
const openAI =
|
||||
apiKey
|
||||
? { availableModels: getOpenAIModels(), userProvide: apiKey === 'user_provided' }
|
||||
: false;
|
||||
const openAI = apiKey
|
||||
? { availableModels: getOpenAIModels(), userProvide: apiKey === 'user_provided' }
|
||||
: false;
|
||||
const bingAI = process.env.BINGAI_TOKEN
|
||||
? { userProvide: process.env.BINGAI_TOKEN == 'user_provided' }
|
||||
: false;
|
||||
|
|
@ -56,4 +57,4 @@ router.get('/', async function (req, res) {
|
|||
res.send(JSON.stringify({ azureOpenAI, openAI, google, bingAI, chatGPTBrowser }));
|
||||
});
|
||||
|
||||
module.exports = { router, getOpenAIModels, getChatGPTBrowserModels };
|
||||
module.exports = { router, getOpenAIModels, getChatGPTBrowserModels };
|
||||
|
|
|
|||
|
|
@ -19,5 +19,5 @@ module.exports = {
|
|||
auth,
|
||||
oauth,
|
||||
tokenizer,
|
||||
endpoints,
|
||||
endpoints
|
||||
};
|
||||
|
|
|
|||
|
|
@ -61,4 +61,4 @@ router.get(
|
|||
}
|
||||
);
|
||||
|
||||
module.exports = router;
|
||||
module.exports = router;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ router.get('/', requireJwtAuth, async function (req, res) {
|
|||
console.log('cache hit', key);
|
||||
const cached = cache.get(key);
|
||||
const { pages, pageSize, messages } = cached;
|
||||
res.status(200).send({ conversations: cached[pageNumber], pages, pageNumber, pageSize, messages });
|
||||
res
|
||||
.status(200)
|
||||
.send({ conversations: cached[pageNumber], pages, pageNumber, pageSize, messages });
|
||||
return;
|
||||
} else {
|
||||
cache.clear();
|
||||
|
|
@ -44,7 +46,7 @@ router.get('/', requireJwtAuth, async function (req, res) {
|
|||
},
|
||||
true
|
||||
)
|
||||
).hits.map(message => {
|
||||
).hits.map((message) => {
|
||||
const { _formatted, ...rest } = message;
|
||||
return {
|
||||
...rest,
|
||||
|
|
@ -95,12 +97,12 @@ router.get('/clear', async function (req, res) {
|
|||
|
||||
router.get('/test', async function (req, res) {
|
||||
const { q } = req.query;
|
||||
const messages = (await Message.meiliSearch(q, { attributesToHighlight: ['text'] }, true)).hits.map(
|
||||
message => {
|
||||
const { _formatted, ...rest } = message;
|
||||
return { ...rest, searchResult: true, text: _formatted.text };
|
||||
}
|
||||
);
|
||||
const messages = (
|
||||
await Message.meiliSearch(q, { attributesToHighlight: ['text'] }, true)
|
||||
).hits.map((message) => {
|
||||
const { _formatted, ...rest } = message;
|
||||
return { ...rest, searchResult: true, text: _formatted.text };
|
||||
});
|
||||
res.send(messages);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ const registerUser = async (user) => {
|
|||
}
|
||||
|
||||
//determine if this is the first registered user (not counting anonymous_user)
|
||||
const isFirstRegisteredUser = await User.countDocuments({}) === 0;
|
||||
const isFirstRegisteredUser = (await User.countDocuments({})) === 0;
|
||||
|
||||
try {
|
||||
const newUser = await new User({
|
||||
|
|
@ -88,7 +88,7 @@ const registerUser = async (user) => {
|
|||
username,
|
||||
name,
|
||||
avatar: null,
|
||||
role: isFirstRegisteredUser ? 'ADMIN' : 'USER',
|
||||
role: isFirstRegisteredUser ? 'ADMIN' : 'USER'
|
||||
});
|
||||
|
||||
// todo: implement refresh token
|
||||
|
|
@ -104,7 +104,7 @@ const registerUser = async (user) => {
|
|||
newUser.save();
|
||||
});
|
||||
});
|
||||
console.log('newUser', newUser)
|
||||
console.log('newUser', newUser);
|
||||
if (isFirstRegisteredUser) {
|
||||
migrateDataToFirstUser(newUser);
|
||||
// console.log(migrate);
|
||||
|
|
@ -186,12 +186,11 @@ const resetPassword = async (userId, token, password) => {
|
|||
return { message: 'Password reset was successful' };
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
// signup,
|
||||
registerUser,
|
||||
loginUser,
|
||||
logoutUser,
|
||||
requestPasswordReset,
|
||||
resetPassword,
|
||||
resetPassword
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const passport = require('passport');
|
||||
const FacebookStrategy = require('passport-facebook').Strategy;
|
||||
const passport = require('passport');
|
||||
const FacebookStrategy = require('passport-facebook').Strategy;
|
||||
const User = require('../models/User');
|
||||
|
||||
|
||||
const serverUrl =
|
||||
process.env.NODE_ENV === 'production' ? process.env.SERVER_URL_PROD : process.env.SERVER_URL_DEV;
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ const facebookLogin = new FacebookStrategy(
|
|||
clientID: process.env.FACEBOOK_APP_ID,
|
||||
clientSecret: process.env.FACEBOOK_SECRET,
|
||||
callbackURL: `${serverUrl}${process.env.FACEBOOK_CALLBACK_URL}`,
|
||||
proxy: true,
|
||||
proxy: true
|
||||
// profileFields: [
|
||||
// 'id',
|
||||
// 'email',
|
||||
|
|
|
|||
|
|
@ -65,4 +65,3 @@ function log({ title, parameters }) {
|
|||
DebugControl.log.parameters(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,4 +21,4 @@ const registerSchema = Joi.object().keys({
|
|||
module.exports = {
|
||||
loginSchema,
|
||||
registerSchema
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ const pino = require('pino');
|
|||
const logger = pino({
|
||||
level: 'info',
|
||||
redact: {
|
||||
paths: [ // List of Paths to redact from the logs (https://getpino.io/#/docs/redaction)
|
||||
paths: [
|
||||
// List of Paths to redact from the logs (https://getpino.io/#/docs/redaction)
|
||||
'env.OPENAI_KEY',
|
||||
'env.BINGAI_TOKEN',
|
||||
'env.CHATGPT_TOKEN',
|
||||
|
|
@ -11,14 +12,16 @@ const logger = pino({
|
|||
'env.GOOGLE_CLIENT_SECRET',
|
||||
'env.JWT_SECRET_DEV',
|
||||
'env.JWT_SECRET_PROD',
|
||||
'newUser.password'], // See example to filter object class instances
|
||||
censor: '***', // Redaction character
|
||||
},
|
||||
'newUser.password'
|
||||
], // See example to filter object class instances
|
||||
censor: '***' // Redaction character
|
||||
}
|
||||
});
|
||||
|
||||
// Sanitize outside the logger paths. This is useful for sanitizing variables directly with Regex and patterns.
|
||||
const redactPatterns = [ // Array of regular expressions for redacting patterns
|
||||
/api[-_]?key/i,
|
||||
const redactPatterns = [
|
||||
// Array of regular expressions for redacting patterns
|
||||
/api[-_]?key/i,
|
||||
/password/i,
|
||||
/token/i,
|
||||
/secret/i,
|
||||
|
|
@ -30,7 +33,7 @@ const redactPatterns = [ // Array of regular expressions for redacting patterns
|
|||
/authorization[-_]?acr[-_]?values/i,
|
||||
/authorization[-_]?response[-_]?mode/i,
|
||||
/authorization[-_]?nonce/i
|
||||
];
|
||||
];
|
||||
|
||||
/*
|
||||
// Example of redacting sensitive data from object class instances
|
||||
|
|
@ -49,21 +52,19 @@ const redactPatterns = [ // Array of regular expressions for redacting patterns
|
|||
*/
|
||||
|
||||
const levels = {
|
||||
TRACE: 10,
|
||||
DEBUG: 20,
|
||||
INFO: 30,
|
||||
WARN: 40,
|
||||
ERROR: 50,
|
||||
FATAL: 60
|
||||
TRACE: 10,
|
||||
DEBUG: 20,
|
||||
INFO: 30,
|
||||
WARN: 40,
|
||||
ERROR: 50,
|
||||
FATAL: 60
|
||||
};
|
||||
|
||||
|
||||
|
||||
let level = levels.INFO;
|
||||
|
||||
module.exports = {
|
||||
levels,
|
||||
setLevel: (l) => (level = l),
|
||||
setLevel: l => (level = l),
|
||||
log: {
|
||||
trace: (msg) => {
|
||||
if (level <= levels.TRACE) return;
|
||||
|
|
@ -122,4 +123,3 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
function genAzureEndpoint({ azureOpenAIApiInstanceName, azureOpenAIApiDeploymentName, azureOpenAIApiVersion }) {
|
||||
function genAzureEndpoint({
|
||||
azureOpenAIApiInstanceName,
|
||||
azureOpenAIApiDeploymentName,
|
||||
azureOpenAIApiVersion
|
||||
}) {
|
||||
return `https://${azureOpenAIApiInstanceName}.openai.azure.com/openai/deployments/${azureOpenAIApiDeploymentName}/chat/completions?api-version=${azureOpenAIApiVersion}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,28 +3,27 @@ const Preset = require('../models/schema/presetSchema');
|
|||
|
||||
const migrateConversations = async (userId) => {
|
||||
try {
|
||||
return await Conversation.updateMany({ user: null }, { $set: { user: userId }}).exec();
|
||||
return await Conversation.updateMany({ user: null }, { $set: { user: userId } }).exec();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return { message: 'Error saving conversation' };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const migratePresets = async (userId) => {
|
||||
try {
|
||||
return await Preset.updateMany({ user: null }, { $set: { user: userId }}).exec();
|
||||
return await Preset.updateMany({ user: null }, { $set: { user: userId } }).exec();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return { message: 'Error saving conversation' };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const migrateDataToFirstUser = async (user) => {
|
||||
const conversations = await migrateConversations(user.id);
|
||||
console.log(conversations);
|
||||
const presets = await migratePresets(user.id);
|
||||
console.log(presets);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = migrateDataToFirstUser;
|
||||
module.exports = migrateDataToFirstUser;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const nodemailer = require("nodemailer");
|
||||
const handlebars = require("handlebars");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const nodemailer = require('nodemailer');
|
||||
const handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const sendEmail = async (email, subject, payload, template) => {
|
||||
try {
|
||||
|
|
@ -11,18 +11,18 @@ const sendEmail = async (email, subject, payload, template) => {
|
|||
port: 465,
|
||||
auth: {
|
||||
user: process.env.EMAIL_USERNAME,
|
||||
pass: process.env.EMAIL_PASSWORD,
|
||||
},
|
||||
pass: process.env.EMAIL_PASSWORD
|
||||
}
|
||||
});
|
||||
|
||||
const source = fs.readFileSync(path.join(__dirname, template), "utf8");
|
||||
const source = fs.readFileSync(path.join(__dirname, template), 'utf8');
|
||||
const compiledTemplate = handlebars.compile(source);
|
||||
const options = () => {
|
||||
return {
|
||||
from: process.env.FROM_EMAIL,
|
||||
to: email,
|
||||
subject: subject,
|
||||
html: compiledTemplate(payload),
|
||||
html: compiledTemplate(payload)
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ const sendEmail = async (email, subject, payload, template) => {
|
|||
return error;
|
||||
} else {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
success: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -51,4 +51,4 @@ sendEmail(
|
|||
);
|
||||
*/
|
||||
|
||||
module.exports = sendEmail;
|
||||
module.exports = sendEmail;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue