diff --git a/default/config.yaml b/default/config.yaml index a9d38a4d0..513b129fa 100644 --- a/default/config.yaml +++ b/default/config.yaml @@ -65,6 +65,8 @@ autheliaAuth: false # the username and passwords for basic auth are the same as those # for the individual accounts perUserBasicAuth: false +# Minimum log level to display in the terminal (DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3) +minLogLevel: 0 # User session timeout *in seconds* (defaults to 24 hours). ## Set to a positive number to expire session after a certain time of inactivity diff --git a/public/scripts/chat-templates.js b/public/scripts/chat-templates.js index ea732b90c..6797f1cf5 100644 --- a/public/scripts/chat-templates.js +++ b/public/scripts/chat-templates.js @@ -59,6 +59,7 @@ const hash_derivations = { // Tulu-3-8B // Tulu-3-70B 'Tulu' + , }; const substr_derivations = { @@ -87,6 +88,6 @@ export async function deriveTemplatesFromChatTemplate(chat_template, hash) { } } - console.log(`Unknown chat template hash: ${hash} for [${chat_template}]`); + console.warn(`Unknown chat template hash: ${hash} for [${chat_template}]`); return null; } diff --git a/public/scripts/extensions/quick-reply/src/QuickReplySet.js b/public/scripts/extensions/quick-reply/src/QuickReplySet.js index 337957069..5ac637b44 100644 --- a/public/scripts/extensions/quick-reply/src/QuickReplySet.js +++ b/public/scripts/extensions/quick-reply/src/QuickReplySet.js @@ -1,15 +1,13 @@ import { getRequestHeaders, substituteParams } from '../../../../script.js'; import { Popup, POPUP_RESULT, POPUP_TYPE } from '../../../popup.js'; -import { executeSlashCommands, executeSlashCommandsOnChatInput, executeSlashCommandsWithOptions } from '../../../slash-commands.js'; +import { executeSlashCommandsOnChatInput, executeSlashCommandsWithOptions } from '../../../slash-commands.js'; import { SlashCommandParser } from '../../../slash-commands/SlashCommandParser.js'; -import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js'; -import { debounceAsync, log, warn } from '../index.js'; +import { debounceAsync, warn } from '../index.js'; import { QuickReply } from './QuickReply.js'; export class QuickReplySet { /**@type {QuickReplySet[]}*/ static list = []; - static from(props) { props.qrList = []; //props.qrList?.map(it=>QuickReply.from(it)); const instance = Object.assign(new this(), props); @@ -24,9 +22,6 @@ export class QuickReplySet { return this.list.find(it=>it.name == name); } - - - /**@type {string}*/ name; /**@type {boolean}*/ disableSend = false; /**@type {boolean}*/ placeBeforeInput = false; @@ -34,19 +29,12 @@ export class QuickReplySet { /**@type {string}*/ color = 'transparent'; /**@type {boolean}*/ onlyBorderColor = false; /**@type {QuickReply[]}*/ qrList = []; - /**@type {number}*/ idIndex = 0; - /**@type {boolean}*/ isDeleted = false; - /**@type {function}*/ save; - /**@type {HTMLElement}*/ dom; /**@type {HTMLElement}*/ settingsDom; - - - constructor() { this.save = debounceAsync(()=>this.performSave(), 200); } @@ -55,9 +43,6 @@ export class QuickReplySet { this.qrList.forEach(qr=>this.hookQuickReply(qr)); } - - - unrender() { this.dom?.remove(); this.dom = null; @@ -100,9 +85,6 @@ export class QuickReplySet { } } - - - renderSettings() { if (!this.settingsDom) { this.settingsDom = document.createElement('div'); { @@ -123,9 +105,6 @@ export class QuickReplySet { this.settingsDom.append(qr.renderSettings(idx)); } - - - /** * * @param {QuickReply} qr @@ -138,6 +117,7 @@ export class QuickReplySet { closure.scope.setMacro('arg::*', ''); return (await closure.execute())?.pipe; } + /** * * @param {QuickReply} qr The QR to execute. @@ -207,6 +187,7 @@ export class QuickReplySet { document.querySelector('#send_but').click(); } } + /** * @param {QuickReply} qr * @param {string} [message] - optional altered message to be used @@ -220,9 +201,6 @@ export class QuickReplySet { }); } - - - addQuickReply(data = {}) { const id = Math.max(this.idIndex, this.qrList.reduce((max,qr)=>Math.max(max,qr.id),0)) + 1; data.id = @@ -239,6 +217,7 @@ export class QuickReplySet { this.save(); return qr; } + addQuickReplyFromText(qrJson) { let data; if (qrJson) { @@ -371,7 +350,6 @@ export class QuickReplySet { this.save(); } - toJSON() { return { version: 2, @@ -386,7 +364,6 @@ export class QuickReplySet { }; } - async performSave() { const response = await fetch('/api/quick-replies/save', { method: 'POST', diff --git a/public/scripts/extensions/vectors/index.js b/public/scripts/extensions/vectors/index.js index 30278ddea..aea42d909 100644 --- a/public/scripts/extensions/vectors/index.js +++ b/public/scripts/extensions/vectors/index.js @@ -1621,14 +1621,14 @@ jQuery(async () => { const attachments = source ? getDataBankAttachmentsForSource(source, false) : getDataBankAttachments(false); const collectionIds = await ingestDataBankAttachments(String(source)); const queryResults = await queryMultipleCollections(collectionIds, String(query), count, threshold); - + // Get URLs const urls = Object .keys(queryResults) .map(x => attachments.find(y => getFileCollectionId(y.url) === x)) .filter(x => x) .map(x => x.url); - + // Gets the actual text content of chunks const getChunksText = () => { let textResult = ''; @@ -1638,14 +1638,12 @@ jQuery(async () => { } return textResult; }; - if (args.return === 'chunks') { return getChunksText(); } // @ts-ignore return slashCommandReturnHelper.doReturn(args.return ?? 'object', urls, { objectToStringFunc: list => list.join('\n') }); - }, aliases: ['databank-search', 'data-bank-search'], helpString: 'Search the Data Bank for a specific query using vector similarity. Returns a list of file URLs with the most relevant content.', @@ -1660,10 +1658,10 @@ jQuery(async () => { defaultValue: 'object', enumList: [ new SlashCommandEnumValue('chunks', 'Return the actual content chunks', enumTypes.enum, '{}'), - ...slashCommandReturnHelper.enumList({ allowObject: true }) + ...slashCommandReturnHelper.enumList({ allowObject: true }), ], forceEnum: true, - }) + }), ], unnamedArgumentList: [ new SlashCommandArgument('Query to search by.', ARGUMENT_TYPE.STRING, true, false), diff --git a/server.js b/server.js index db7ba9306..b3ee0e8a2 100644 --- a/server.js +++ b/server.js @@ -67,6 +67,7 @@ import { forwardFetchResponse, removeColorFormatting, getSeparator, + setupLogLevel, } from './src/util.js'; import { UPLOADS_DIRECTORY } from './src/constants.js'; import { ensureThumbnailCache } from './src/endpoints/thumbnails.js'; @@ -688,8 +689,9 @@ const preSetupTasks = async function () { function getAutorunHostname() { if (autorunHostname === 'auto') { if (enableIPv6 && enableIPv4) { - if (avoidLocalhost) return '[::1]'; - return 'localhost'; + return avoidLocalhost + ? '[::1]' + : 'localhost'; } if (enableIPv6) { @@ -755,6 +757,8 @@ const postSetupTasks = async function (v6Failed, v4Failed) { } } } + + setupLogLevel(); }; /** diff --git a/src/constants.js b/src/constants.js index 35118a04b..c710a5806 100644 --- a/src/constants.js +++ b/src/constants.js @@ -413,3 +413,10 @@ export const VLLM_KEYS = [ 'guided_decoding_backend', 'guided_whitespace_pattern', ]; + +export const LOG_LEVELS = { + DEBUG: 0, + INFO: 1, + WARN: 2, + ERROR: 3, +}; diff --git a/src/endpoints/anthropic.js b/src/endpoints/anthropic.js index 79f3fc5e9..a041cb0a5 100644 --- a/src/endpoints/anthropic.js +++ b/src/endpoints/anthropic.js @@ -32,7 +32,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { max_tokens: 4096, }; - console.log('Multimodal captioning request', body); + console.debug('Multimodal captioning request', body); const result = await fetch(url, { body: JSON.stringify(body), @@ -46,14 +46,14 @@ router.post('/caption-image', jsonParser, async (request, response) => { if (!result.ok) { const text = await result.text(); - console.log(`Claude API returned error: ${result.status} ${result.statusText}`, text); + console.error(`Claude API returned error: ${result.status} ${result.statusText}`, text); return response.status(result.status).send({ error: true }); } /** @type {any} */ const generateResponseJson = await result.json(); const caption = generateResponseJson.content[0].text; - console.log('Claude response:', generateResponseJson); + console.debug('Claude response:', generateResponseJson); if (!caption) { return response.status(500).send('No caption found'); diff --git a/src/endpoints/assets.js b/src/endpoints/assets.js index a9d7fd201..434601fc9 100644 --- a/src/endpoints/assets.js +++ b/src/endpoints/assets.js @@ -176,7 +176,7 @@ router.post('/get', jsonParser, async (request, response) => { } } catch (err) { - console.log(err); + console.error(err); } return response.send(output); }); @@ -200,7 +200,7 @@ router.post('/download', jsonParser, async (request, response) => { category = i; if (category === null) { - console.debug('Bad request: unsupported asset category.'); + console.error('Bad request: unsupported asset category.'); return response.sendStatus(400); } @@ -212,7 +212,7 @@ router.post('/download', jsonParser, async (request, response) => { const temp_path = path.join(request.user.directories.assets, 'temp', request.body.filename); const file_path = path.join(request.user.directories.assets, category, request.body.filename); - console.debug('Request received to download', url, 'to', file_path); + console.info('Request received to download', url, 'to', file_path); try { // Download to temp @@ -224,7 +224,9 @@ router.post('/download', jsonParser, async (request, response) => { // Delete if previous download failed if (fs.existsSync(temp_path)) { fs.unlink(temp_path, (err) => { - if (err) throw err; + if (err) { + throw err; + } }); } const fileStream = fs.createWriteStream(destination, { flags: 'wx' }); @@ -241,13 +243,13 @@ router.post('/download', jsonParser, async (request, response) => { } // Move into asset place - console.debug('Download finished, moving file from', temp_path, 'to', file_path); + console.info('Download finished, moving file from', temp_path, 'to', file_path); fs.copyFileSync(temp_path, file_path); fs.rmSync(temp_path); response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); response.sendStatus(500); } }); @@ -270,7 +272,7 @@ router.post('/delete', jsonParser, async (request, response) => { category = i; if (category === null) { - console.debug('Bad request: unsupported asset category.'); + console.error('Bad request: unsupported asset category.'); return response.sendStatus(400); } @@ -280,25 +282,27 @@ router.post('/delete', jsonParser, async (request, response) => { return response.status(400).send(validation.message); const file_path = path.join(request.user.directories.assets, category, request.body.filename); - console.debug('Request received to delete', category, file_path); + console.info('Request received to delete', category, file_path); try { // Delete if previous download failed if (fs.existsSync(file_path)) { fs.unlink(file_path, (err) => { - if (err) throw err; + if (err) { + throw err; + } }); - console.debug('Asset deleted.'); + console.info('Asset deleted.'); } else { - console.debug('Asset not found.'); + console.error('Asset not found.'); response.sendStatus(400); } // Move into asset place response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); response.sendStatus(500); } }); @@ -313,19 +317,24 @@ router.post('/delete', jsonParser, async (request, response) => { * @returns {void} */ router.post('/character', jsonParser, async (request, response) => { - if (request.query.name === undefined) return response.sendStatus(400); + if (request.query.name === undefined) { + return response.sendStatus(400); + } + // For backwards compatibility, don't reject invalid character names, just sanitize them const name = sanitize(request.query.name.toString()); const inputCategory = request.query.category; // Check category let category = null; - for (let i of VALID_CATEGORIES) - if (i == inputCategory) + for (let i of VALID_CATEGORIES) { + if (i == inputCategory) { category = i; + } + } if (category === null) { - console.debug('Bad request: unsupported asset category.'); + console.error('Bad request: unsupported asset category.'); return response.sendStatus(400); } @@ -339,7 +348,9 @@ router.post('/character', jsonParser, async (request, response) => { if (category == 'live2d') { const folders = fs.readdirSync(folderPath, { withFileTypes: true }); for (const folderInfo of folders) { - if (!folderInfo.isDirectory()) continue; + if (!folderInfo.isDirectory()) { + continue; + } const modelFolder = folderInfo.name; const live2dModelPath = path.join(folderPath, modelFolder); @@ -364,7 +375,7 @@ router.post('/character', jsonParser, async (request, response) => { return response.send(output); } catch (err) { - console.log(err); + console.error(err); return response.sendStatus(500); } }); diff --git a/src/endpoints/backends/chat-completions.js b/src/endpoints/backends/chat-completions.js index 252e16d95..771f29855 100644 --- a/src/endpoints/backends/chat-completions.js +++ b/src/endpoints/backends/chat-completions.js @@ -230,7 +230,7 @@ async function sendScaleRequest(request, response) { } const requestPrompt = convertTextCompletionPrompt(request.body.messages); - console.log('Scale request:', requestPrompt); + console.debug('Scale request:', requestPrompt); try { const controller = new AbortController(); @@ -249,18 +249,18 @@ async function sendScaleRequest(request, response) { }); if (!generateResponse.ok) { - console.log(`Scale API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); + console.error(`Scale API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); return response.status(500).send({ error: true }); } /** @type {any} */ const generateResponseJson = await generateResponse.json(); - console.log('Scale response:', generateResponseJson); + console.debug('Scale response:', generateResponseJson); const reply = { choices: [{ 'message': { 'content': generateResponseJson.output } }] }; return response.send(reply); } catch (error) { - console.log(error); + console.error(error); if (!response.headersSent) { return response.status(500).send({ error: true }); } @@ -277,7 +277,7 @@ async function sendMakerSuiteRequest(request, response) { const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE); if (!request.body.reverse_proxy && !apiKey) { - console.log('Google AI Studio API key is missing.'); + console.error('Google AI Studio API key is missing.'); return response.status(400).send({ error: true }); } @@ -328,7 +328,7 @@ async function sendMakerSuiteRequest(request, response) { } const body = getGeminiBody(); - console.log('Google AI Studio request:', body); + console.debug('Google AI Studio request:', body); try { const controller = new AbortController(); @@ -355,14 +355,14 @@ async function sendMakerSuiteRequest(request, response) { // Pipe remote SSE stream to Express response forwardFetchResponse(generateResponse, response); } catch (error) { - console.log('Error forwarding streaming response:', error); + console.error('Error forwarding streaming response:', error); if (!response.headersSent) { return response.status(500).send({ error: true }); } } } else { if (!generateResponse.ok) { - console.log(`Google AI Studio API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); + console.error(`Google AI Studio API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); return response.status(generateResponse.status).send({ error: true }); } @@ -380,7 +380,7 @@ async function sendMakerSuiteRequest(request, response) { } const responseContent = candidates[0].content ?? candidates[0].output; - console.log('Google AI Studio response:', responseContent); + console.error('Google AI Studio response:', responseContent); if (Array.isArray(responseContent?.parts) && isThinking && !showThoughts) { responseContent.parts = responseContent.parts.filter(part => !part.thought); @@ -389,7 +389,7 @@ async function sendMakerSuiteRequest(request, response) { const responseText = typeof responseContent === 'string' ? responseContent : responseContent?.parts?.map(part => part.text)?.join('\n\n'); if (!responseText) { let message = 'Google AI Studio Candidate text empty'; - console.log(message, generateResponseJson); + console.error(message, generateResponseJson); return response.send({ error: { message } }); } @@ -398,7 +398,7 @@ async function sendMakerSuiteRequest(request, response) { return response.send(reply); } } catch (error) { - console.log('Error communicating with Google AI Studio API: ', error); + console.error('Error communicating with Google AI Studio API: ', error); if (!response.headersSent) { return response.status(500).send({ error: true }); } @@ -411,9 +411,12 @@ async function sendMakerSuiteRequest(request, response) { * @param {express.Response} response Express response */ async function sendAI21Request(request, response) { - if (!request.body) return response.sendStatus(400); + if (!request.body) { + return response.sendStatus(400); + } + const controller = new AbortController(); - console.log(request.body.messages); + console.debug(request.body.messages); request.socket.removeAllListeners('close'); request.socket.on('close', function () { controller.abort(); @@ -439,7 +442,7 @@ async function sendAI21Request(request, response) { signal: controller.signal, }; - console.log('AI21 request:', body); + console.debug('AI21 request:', body); try { const generateResponse = await fetch(API_AI21 + '/chat/completions', options); @@ -448,16 +451,16 @@ async function sendAI21Request(request, response) { } else { if (!generateResponse.ok) { const errorText = await generateResponse.text(); - console.log(`AI21 API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); + console.error(`AI21 API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); const errorJson = tryParse(errorText) ?? { error: true }; return response.status(500).send(errorJson); } const generateResponseJson = await generateResponse.json(); - console.log('AI21 response:', generateResponseJson); + console.debug('AI21 response:', generateResponseJson); return response.send(generateResponseJson); } } catch (error) { - console.log('Error communicating with AI21 API: ', error); + console.error('Error communicating with AI21 API: ', error); if (!response.headersSent) { response.send({ error: true }); } else { @@ -476,7 +479,7 @@ async function sendMistralAIRequest(request, response) { const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI); if (!apiKey) { - console.log('MistralAI API key is missing.'); + console.error('MistralAI API key is missing.'); return response.status(400).send({ error: true }); } @@ -517,7 +520,7 @@ async function sendMistralAIRequest(request, response) { timeout: 0, }; - console.log('MisralAI request:', requestBody); + console.debug('MisralAI request:', requestBody); const generateResponse = await fetch(apiUrl + '/chat/completions', config); if (request.body.stream) { @@ -525,16 +528,16 @@ async function sendMistralAIRequest(request, response) { } else { if (!generateResponse.ok) { const errorText = await generateResponse.text(); - console.log(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); + console.error(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); const errorJson = tryParse(errorText) ?? { error: true }; return response.status(500).send(errorJson); } const generateResponseJson = await generateResponse.json(); - console.log('MistralAI response:', generateResponseJson); + console.debug('MistralAI response:', generateResponseJson); return response.send(generateResponseJson); } } catch (error) { - console.log('Error communicating with MistralAI API: ', error); + console.error('Error communicating with MistralAI API: ', error); if (!response.headersSent) { response.send({ error: true }); } else { @@ -557,7 +560,7 @@ async function sendCohereRequest(request, response) { }); if (!apiKey) { - console.log('Cohere API key is missing.'); + console.error('Cohere API key is missing.'); return response.status(400).send({ error: true }); } @@ -596,7 +599,7 @@ async function sendCohereRequest(request, response) { requestBody.safety_mode = 'OFF'; } - console.log('Cohere request:', requestBody); + console.debug('Cohere request:', requestBody); const config = { method: 'POST', @@ -618,16 +621,16 @@ async function sendCohereRequest(request, response) { const generateResponse = await fetch(apiUrl, config); if (!generateResponse.ok) { const errorText = await generateResponse.text(); - console.log(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); + console.error(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); const errorJson = tryParse(errorText) ?? { error: true }; return response.status(500).send(errorJson); } const generateResponseJson = await generateResponse.json(); - console.log('Cohere response:', generateResponseJson); + console.debug('Cohere response:', generateResponseJson); return response.send(generateResponseJson); } } catch (error) { - console.log('Error communicating with Cohere API: ', error); + console.error('Error communicating with Cohere API: ', error); if (!response.headersSent) { response.send({ error: true }); } else { @@ -684,12 +687,12 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o api_key_openai = readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK); headers = {}; } else { - console.log('This chat completion source is not supported yet.'); + console.error('This chat completion source is not supported yet.'); return response_getstatus_openai.status(400).send({ error: true }); } if (!api_key_openai && !request.body.reverse_proxy && request.body.chat_completion_source !== CHAT_COMPLETION_SOURCES.CUSTOM) { - console.log('Chat Completion API key is missing.'); + console.error('Chat Completion API key is missing.'); return response_getstatus_openai.status(400).send({ error: true }); } @@ -724,23 +727,23 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o }; }); - console.log('Available OpenRouter models:', models); + console.info('Available OpenRouter models:', models); } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) { const models = data?.data; - console.log(models); + console.info(models); } else { const models = data?.data; if (Array.isArray(models)) { const modelIds = models.filter(x => x && typeof x === 'object').map(x => x.id).sort(); - console.log('Available models:', modelIds); + console.info('Available models:', modelIds); } else { - console.log('Chat Completion endpoint did not return a list of models.'); + console.warn('Chat Completion endpoint did not return a list of models.'); } } } else { - console.log('Chat Completion status check failed. Either Access Token is incorrect or API endpoint is down.'); + console.error('Chat Completion status check failed. Either Access Token is incorrect or API endpoint is down.'); response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } }); } } catch (e) { @@ -755,8 +758,7 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o }); router.post('/bias', jsonParser, async function (request, response) { - if (!request.body || !Array.isArray(request.body)) - return response.sendStatus(400); + if (!request.body || !Array.isArray(request.body)) return response.sendStatus(400); try { const result = {}; @@ -773,7 +775,7 @@ router.post('/bias', jsonParser, async function (request, response) { const tokenizer = getSentencepiceTokenizer(model); const instance = await tokenizer?.get(); if (!instance) { - console.warn('Tokenizer not initialized:', model); + console.error('Tokenizer not initialized:', model); return response.send({}); } encodeFunction = (text) => new Uint32Array(instance.encodeIds(text)); @@ -922,7 +924,7 @@ router.post('/generate', jsonParser, function (request, response) { mergeObjectWithYaml(headers, request.body.custom_include_headers); if (request.body.custom_prompt_post_processing) { - console.log('Applying custom prompt post-processing of type', request.body.custom_prompt_post_processing); + console.info('Applying custom prompt post-processing of type', request.body.custom_prompt_post_processing); request.body.messages = postProcessPrompt( request.body.messages, request.body.custom_prompt_post_processing, @@ -967,12 +969,12 @@ router.post('/generate', jsonParser, function (request, response) { request.body.messages = postProcessPrompt(request.body.messages, 'deepseek', getPromptNames(request)); } else { - console.log('This chat completion source is not supported yet.'); + console.error('This chat completion source is not supported yet.'); return response.status(400).send({ error: true }); } if (!apiKey && !request.body.reverse_proxy && request.body.chat_completion_source !== CHAT_COMPLETION_SOURCES.CUSTOM) { - console.log('OpenAI API key is missing.'); + console.error('OpenAI API key is missing.'); return response.status(400).send({ error: true }); } @@ -1032,7 +1034,7 @@ router.post('/generate', jsonParser, function (request, response) { signal: controller.signal, }; - console.log(requestBody); + console.debug(requestBody); makeRequest(config, response, request); @@ -1049,7 +1051,7 @@ router.post('/generate', jsonParser, function (request, response) { const fetchResponse = await fetch(endpointUrl, config); if (request.body.stream) { - console.log('Streaming request in progress'); + console.info('Streaming request in progress'); forwardFetchResponse(fetchResponse, response); return; } @@ -1058,10 +1060,10 @@ router.post('/generate', jsonParser, function (request, response) { /** @type {any} */ let json = await fetchResponse.json(); response.send(json); - console.log(json); - console.log(json?.choices?.[0]?.message); + console.debug(json); + console.debug(json?.choices?.[0]?.message); } else if (fetchResponse.status === 429 && retries > 0) { - console.log(`Out of quota, retrying in ${Math.round(timeout / 1000)}s`); + console.warn(`Out of quota, retrying in ${Math.round(timeout / 1000)}s`); setTimeout(() => { timeout *= 2; makeRequest(config, response, request, retries - 1, timeout); @@ -1070,7 +1072,7 @@ router.post('/generate', jsonParser, function (request, response) { await handleErrorResponse(fetchResponse); } } catch (error) { - console.log('Generation failed', error); + console.error('Generation failed', error); const message = error.code === 'ECONNREFUSED' ? `Connection refused: ${error.message}` : error.message || 'Unknown error occurred'; @@ -1092,7 +1094,7 @@ router.post('/generate', jsonParser, function (request, response) { const message = errorResponse.statusText || 'Unknown error occurred'; const quota_error = errorResponse.status === 429 && errorData?.error?.type === 'insufficient_quota'; - console.log('Chat completion request error: ', message, responseText); + console.error('Chat completion request error: ', message, responseText); if (!response.headersSent) { response.send({ error: { message }, quota_error: quota_error }); diff --git a/src/endpoints/backends/kobold.js b/src/endpoints/backends/kobold.js index a6e7fc89e..4c29a45cb 100644 --- a/src/endpoints/backends/kobold.js +++ b/src/endpoints/backends/kobold.js @@ -22,17 +22,17 @@ router.post('/generate', jsonParser, async function (request, response_generate) request.socket.on('close', async function () { if (request.body.can_abort && !response_generate.writableEnded) { try { - console.log('Aborting Kobold generation...'); + console.info('Aborting Kobold generation...'); // send abort signal to koboldcpp const abortResponse = await fetch(`${request.body.api_server}/extra/abort`, { method: 'POST', }); if (!abortResponse.ok) { - console.log('Error sending abort request to Kobold:', abortResponse.status); + console.error('Error sending abort request to Kobold:', abortResponse.status); } } catch (error) { - console.log(error); + console.error(error); } } controller.abort(); @@ -81,7 +81,7 @@ router.post('/generate', jsonParser, async function (request, response_generate) } } - console.log(this_settings); + console.debug(this_settings); const args = { body: JSON.stringify(this_settings), headers: Object.assign( @@ -105,7 +105,7 @@ router.post('/generate', jsonParser, async function (request, response_generate) } else { if (!response.ok) { const errorText = await response.text(); - console.log(`Kobold returned error: ${response.status} ${response.statusText} ${errorText}`); + console.error(`Kobold returned error: ${response.status} ${response.statusText} ${errorText}`); try { const errorJson = JSON.parse(errorText); @@ -117,7 +117,7 @@ router.post('/generate', jsonParser, async function (request, response_generate) } const data = await response.json(); - console.log('Endpoint response:', data); + console.debug('Endpoint response:', data); return response_generate.send(data); } } catch (error) { @@ -125,19 +125,19 @@ router.post('/generate', jsonParser, async function (request, response_generate) switch (error?.status) { case 403: case 503: // retry in case of temporary service issue, possibly caused by a queue failure? - console.debug(`KoboldAI is busy. Retry attempt ${i + 1} of ${MAX_RETRIES}...`); + console.warn(`KoboldAI is busy. Retry attempt ${i + 1} of ${MAX_RETRIES}...`); await delay(delayAmount); break; default: if ('status' in error) { - console.log('Status Code from Kobold:', error.status); + console.error('Status Code from Kobold:', error.status); } return response_generate.send({ error: true }); } } } - console.log('Max retries exceeded. Giving up.'); + console.error('Max retries exceeded. Giving up.'); return response_generate.send({ error: true }); }); @@ -193,16 +193,17 @@ router.post('/transcribe-audio', urlencodedParser, async function (request, resp const server = request.body.server; if (!server) { - console.log('Server is not set'); + console.error('Server is not set'); return response.sendStatus(400); } if (!request.file) { - console.log('No audio file found'); + console.error('No audio file found'); return response.sendStatus(400); } - console.log('Transcribing audio with KoboldCpp', server); + console.info('Transcribing audio with KoboldCpp'); + console.debug(server); const fileBase64 = fs.readFileSync(request.file.path).toString('base64'); fs.rmSync(request.file.path); @@ -226,12 +227,12 @@ router.post('/transcribe-audio', urlencodedParser, async function (request, resp if (!result.ok) { const text = await result.text(); - console.log('KoboldCpp request failed', result.statusText, text); + console.error('KoboldCpp request failed', result.statusText, text); return response.status(500).send(text); } const data = await result.json(); - console.log('KoboldCpp transcription response', data); + console.debug('KoboldCpp transcription response', data); return response.json(data); } catch (error) { console.error('KoboldCpp transcription failed', error); diff --git a/src/endpoints/backends/scale-alt.js b/src/endpoints/backends/scale-alt.js index 5e621e17c..b2daddded 100644 --- a/src/endpoints/backends/scale-alt.js +++ b/src/endpoints/backends/scale-alt.js @@ -13,7 +13,7 @@ router.post('/generate', jsonParser, async function (request, response) { const cookie = readSecret(request.user.directories, SECRET_KEYS.SCALE_COOKIE); if (!cookie) { - console.log('No Scale cookie found'); + console.error('No Scale cookie found'); return response.sendStatus(400); } @@ -62,7 +62,7 @@ router.post('/generate', jsonParser, async function (request, response) { }, }; - console.log('Scale request:', body); + console.debug('Scale request:', body); const result = await fetch('https://dashboard.scale.com/spellbook/api/trpc/v2.variant.run', { method: 'POST', @@ -75,7 +75,7 @@ router.post('/generate', jsonParser, async function (request, response) { if (!result.ok) { const text = await result.text(); - console.log('Scale request failed', result.statusText, text); + console.error('Scale request failed', result.statusText, text); return response.status(500).send({ error: { message: result.statusText } }); } @@ -83,7 +83,7 @@ router.post('/generate', jsonParser, async function (request, response) { const data = await result.json(); const output = data?.result?.data?.json?.outputs?.[0] || ''; - console.log('Scale response:', data); + console.debug('Scale response:', data); if (!output) { console.warn('Scale response is empty'); @@ -92,7 +92,7 @@ router.post('/generate', jsonParser, async function (request, response) { return response.json({ output }); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); diff --git a/src/endpoints/backends/text-completions.js b/src/endpoints/backends/text-completions.js index 28651e93a..59b579dc1 100644 --- a/src/endpoints/backends/text-completions.js +++ b/src/endpoints/backends/text-completions.js @@ -58,12 +58,12 @@ async function parseOllamaStream(jsonStream, request, response) { }); jsonStream.body.on('end', () => { - console.log('Streaming request finished'); + console.info('Streaming request finished'); response.write('data: [DONE]\n\n'); response.end(); }); } catch (error) { - console.log('Error forwarding streaming response:', error); + console.error('Error forwarding streaming response:', error); if (!response.headersSent) { return response.status(500).send({ error: true }); } else { @@ -79,16 +79,16 @@ async function parseOllamaStream(jsonStream, request, response) { */ async function abortKoboldCppRequest(url) { try { - console.log('Aborting Kobold generation...'); + console.info('Aborting Kobold generation...'); const abortResponse = await fetch(`${url}/api/extra/abort`, { method: 'POST', }); if (!abortResponse.ok) { - console.log('Error sending abort request to Kobold:', abortResponse.status, abortResponse.statusText); + console.error('Error sending abort request to Kobold:', abortResponse.status, abortResponse.statusText); } } catch (error) { - console.log(error); + console.error(error); } } @@ -101,7 +101,8 @@ router.post('/status', jsonParser, async function (request, response) { request.body.api_server = request.body.api_server.replace('localhost', '127.0.0.1'); } - console.log('Trying to connect to API:', request.body); + console.info('Trying to connect to API'); + console.debug(request.body); const baseUrl = trimV1(request.body.api_server); const args = { @@ -123,6 +124,7 @@ router.post('/status', jsonParser, async function (request, response) { case TEXTGEN_TYPES.LLAMACPP: case TEXTGEN_TYPES.INFERMATICAI: case TEXTGEN_TYPES.OPENROUTER: + case TEXTGEN_TYPES.FEATHERLESS: url += '/v1/models'; break; case TEXTGEN_TYPES.DREAMGEN: @@ -140,9 +142,6 @@ router.post('/status', jsonParser, async function (request, response) { case TEXTGEN_TYPES.OLLAMA: url += '/api/tags'; break; - case TEXTGEN_TYPES.FEATHERLESS: - url += '/v1/models'; - break; case TEXTGEN_TYPES.HUGGINGFACE: url += '/info'; break; @@ -152,7 +151,7 @@ router.post('/status', jsonParser, async function (request, response) { const isPossiblyLmStudio = modelsReply.headers.get('x-powered-by') === 'Express'; if (!modelsReply.ok) { - console.log('Models endpoint is offline.'); + console.error('Models endpoint is offline.'); return response.sendStatus(400); } @@ -173,12 +172,12 @@ router.post('/status', jsonParser, async function (request, response) { } if (!Array.isArray(data.data)) { - console.log('Models response is not an array.'); + console.error('Models response is not an array.'); return response.sendStatus(400); } const modelIds = data.data.map(x => x.id); - console.log('Models available:', modelIds); + console.info('Models available:', modelIds); // Set result to the first model ID result = modelIds[0] || 'Valid'; @@ -191,7 +190,7 @@ router.post('/status', jsonParser, async function (request, response) { if (modelInfoReply.ok) { /** @type {any} */ const modelInfo = await modelInfoReply.json(); - console.log('Ooba model info:', modelInfo); + console.debug('Ooba model info:', modelInfo); const modelName = modelInfo?.model_name; result = modelName || result; @@ -208,7 +207,7 @@ router.post('/status', jsonParser, async function (request, response) { if (modelInfoReply.ok) { /** @type {any} */ const modelInfo = await modelInfoReply.json(); - console.log('Tabby model info:', modelInfo); + console.debug('Tabby model info:', modelInfo); const modelName = modelInfo?.id; result = modelName || result; @@ -230,7 +229,9 @@ router.post('/status', jsonParser, async function (request, response) { }); router.post('/props', jsonParser, async function (request, response) { - if (!request.body.api_server) return response.sendStatus(400); + if (!request.body.api_server) { + return response.sendStatus(400); + } try { const baseUrl = trimV1(request.body.api_server); @@ -255,7 +256,7 @@ router.post('/props', jsonParser, async function (request, response) { props['chat_template'] = props['chat_template'].slice(0, -1) + '\n'; } props['chat_template_hash'] = createHash('sha256').update(props['chat_template']).digest('hex'); - console.log(`Model properties: ${JSON.stringify(props)}`); + console.debug(`Model properties: ${JSON.stringify(props)}`); return response.send(props); } catch (error) { console.error(error); @@ -264,7 +265,9 @@ router.post('/props', jsonParser, async function (request, response) { }); router.post('/generate', jsonParser, async function (request, response) { - if (!request.body) return response.sendStatus(400); + if (!request.body) { + return response.sendStatus(400); + } try { if (request.body.api_server.indexOf('localhost') !== -1) { @@ -273,7 +276,7 @@ router.post('/generate', jsonParser, async function (request, response) { const apiType = request.body.api_type; const baseUrl = request.body.api_server; - console.log(request.body); + console.debug(request.body); const controller = new AbortController(); request.socket.removeAllListeners('close'); @@ -399,7 +402,7 @@ router.post('/generate', jsonParser, async function (request, response) { if (completionsReply.ok) { /** @type {any} */ const data = await completionsReply.json(); - console.log('Endpoint response:', data); + console.debug('Endpoint response:', data); // Map InfermaticAI response to OAI completions format if (apiType === TEXTGEN_TYPES.INFERMATICAI) { @@ -411,24 +414,20 @@ router.post('/generate', jsonParser, async function (request, response) { const text = await completionsReply.text(); const errorBody = { error: true, status: completionsReply.status, response: text }; - if (!response.headersSent) { - return response.send(errorBody); - } - - return response.end(); + return !response.headersSent + ? response.send(errorBody) + : response.end(); } } } catch (error) { const status = error?.status ?? error?.code ?? 'UNKNOWN'; const text = error?.error ?? error?.statusText ?? error?.message ?? 'Unknown error on /generate endpoint'; let value = { error: true, status: status, response: text }; - console.log('Endpoint error:', error); + console.error('Endpoint error:', error); - if (!response.headersSent) { - return response.send(value); - } - - return response.end(); + return !response.headersSent + ? response.send(value) + : response.end(); } }); @@ -436,7 +435,9 @@ const ollama = express.Router(); ollama.post('/download', jsonParser, async function (request, response) { try { - if (!request.body.name || !request.body.api_server) return response.sendStatus(400); + if (!request.body.name || !request.body.api_server) { + return response.sendStatus(400); + } const name = request.body.name; const url = String(request.body.api_server).replace(/\/$/, ''); @@ -451,7 +452,7 @@ ollama.post('/download', jsonParser, async function (request, response) { }); if (!fetchResponse.ok) { - console.log('Download error:', fetchResponse.status, fetchResponse.statusText); + console.error('Download error:', fetchResponse.status, fetchResponse.statusText); return response.status(fetchResponse.status).send({ error: true }); } @@ -468,7 +469,7 @@ ollama.post('/caption-image', jsonParser, async function (request, response) { return response.sendStatus(400); } - console.log('Ollama caption request:', request.body); + console.debug('Ollama caption request:', request.body); const baseUrl = trimV1(request.body.server_url); const fetchResponse = await fetch(`${baseUrl}/api/generate`, { @@ -483,18 +484,18 @@ ollama.post('/caption-image', jsonParser, async function (request, response) { }); if (!fetchResponse.ok) { - console.log('Ollama caption error:', fetchResponse.status, fetchResponse.statusText); + console.error('Ollama caption error:', fetchResponse.status, fetchResponse.statusText); return response.status(500).send({ error: true }); } /** @type {any} */ const data = await fetchResponse.json(); - console.log('Ollama caption response:', data); + console.debug('Ollama caption response:', data); const caption = data?.response || ''; if (!caption) { - console.log('Ollama caption is empty.'); + console.error('Ollama caption is empty.'); return response.status(500).send({ error: true }); } @@ -513,7 +514,7 @@ llamacpp.post('/caption-image', jsonParser, async function (request, response) { return response.sendStatus(400); } - console.log('LlamaCpp caption request:', request.body); + console.debug('LlamaCpp caption request:', request.body); const baseUrl = trimV1(request.body.server_url); const fetchResponse = await fetch(`${baseUrl}/completion`, { @@ -529,18 +530,18 @@ llamacpp.post('/caption-image', jsonParser, async function (request, response) { }); if (!fetchResponse.ok) { - console.log('LlamaCpp caption error:', fetchResponse.status, fetchResponse.statusText); + console.error('LlamaCpp caption error:', fetchResponse.status, fetchResponse.statusText); return response.status(500).send({ error: true }); } /** @type {any} */ const data = await fetchResponse.json(); - console.log('LlamaCpp caption response:', data); + console.debug('LlamaCpp caption response:', data); const caption = data?.content || ''; if (!caption) { - console.log('LlamaCpp caption is empty.'); + console.error('LlamaCpp caption is empty.'); return response.status(500).send({ error: true }); } @@ -558,7 +559,7 @@ llamacpp.post('/props', jsonParser, async function (request, response) { return response.sendStatus(400); } - console.log('LlamaCpp props request:', request.body); + console.debug('LlamaCpp props request:', request.body); const baseUrl = trimV1(request.body.server_url); const fetchResponse = await fetch(`${baseUrl}/props`, { @@ -566,12 +567,12 @@ llamacpp.post('/props', jsonParser, async function (request, response) { }); if (!fetchResponse.ok) { - console.log('LlamaCpp props error:', fetchResponse.status, fetchResponse.statusText); + console.error('LlamaCpp props error:', fetchResponse.status, fetchResponse.statusText); return response.status(500).send({ error: true }); } const data = await fetchResponse.json(); - console.log('LlamaCpp props response:', data); + console.debug('LlamaCpp props response:', data); return response.send(data); @@ -590,7 +591,7 @@ llamacpp.post('/slots', jsonParser, async function (request, response) { return response.sendStatus(400); } - console.log('LlamaCpp slots request:', request.body); + console.debug('LlamaCpp slots request:', request.body); const baseUrl = trimV1(request.body.server_url); let fetchResponse; @@ -616,12 +617,12 @@ llamacpp.post('/slots', jsonParser, async function (request, response) { } if (!fetchResponse.ok) { - console.log('LlamaCpp slots error:', fetchResponse.status, fetchResponse.statusText); + console.error('LlamaCpp slots error:', fetchResponse.status, fetchResponse.statusText); return response.status(500).send({ error: true }); } const data = await fetchResponse.json(); - console.log('LlamaCpp slots response:', data); + console.debug('LlamaCpp slots response:', data); return response.send(data); @@ -659,14 +660,14 @@ tabby.post('/download', jsonParser, async function (request, response) { return response.status(403).send({ error: true }); } } else { - console.log('API Permission error:', permissionResponse.status, permissionResponse.statusText); + console.error('API Permission error:', permissionResponse.status, permissionResponse.statusText); return response.status(permissionResponse.status).send({ error: true }); } const fetchResponse = await fetch(`${baseUrl}/v1/download`, args); if (!fetchResponse.ok) { - console.log('Download error:', fetchResponse.status, fetchResponse.statusText); + console.error('Download error:', fetchResponse.status, fetchResponse.statusText); return response.status(fetchResponse.status).send({ error: true }); } diff --git a/src/endpoints/backgrounds.js b/src/endpoints/backgrounds.js index 0638415e6..89b3c0c8a 100644 --- a/src/endpoints/backgrounds.js +++ b/src/endpoints/backgrounds.js @@ -26,7 +26,7 @@ router.post('/delete', jsonParser, function (request, response) { const fileName = path.join(request.user.directories.backgrounds, sanitize(request.body.bg)); if (!fs.existsSync(fileName)) { - console.log('BG file not found'); + console.error('BG file not found'); return response.sendStatus(400); } @@ -42,12 +42,12 @@ router.post('/rename', jsonParser, function (request, response) { const newFileName = path.join(request.user.directories.backgrounds, sanitize(request.body.new_bg)); if (!fs.existsSync(oldFileName)) { - console.log('BG file not found'); + console.error('BG file not found'); return response.sendStatus(400); } if (fs.existsSync(newFileName)) { - console.log('New BG file already exists'); + console.error('New BG file already exists'); return response.sendStatus(400); } diff --git a/src/endpoints/caption.js b/src/endpoints/caption.js index 8fc312ed7..07e27e1b1 100644 --- a/src/endpoints/caption.js +++ b/src/endpoints/caption.js @@ -2,10 +2,10 @@ import express from 'express'; import { jsonParser } from '../express-common.js'; import { getPipeline, getRawImage } from '../transformers.js'; -const TASK = 'image-to-text'; - export const router = express.Router(); +const TASK = 'image-to-text'; + router.post('/', jsonParser, async (req, res) => { try { const { image } = req.body; @@ -13,14 +13,14 @@ router.post('/', jsonParser, async (req, res) => { const rawImage = await getRawImage(image); if (!rawImage) { - console.log('Failed to parse captioned image'); + console.error('Failed to parse captioned image'); return res.sendStatus(400); } const pipe = await getPipeline(TASK); const result = await pipe(rawImage); const text = result[0].generated_text; - console.log('Image caption:', text); + console.debug('Image caption:', text); return res.json({ caption: text }); } catch (error) { diff --git a/src/endpoints/characters.js b/src/endpoints/characters.js index 2aa2cca10..7ad9d2f43 100644 --- a/src/endpoints/characters.js +++ b/src/endpoints/characters.js @@ -90,7 +90,7 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u writeFileAtomicSync(outputImagePath, outputImage); return true; } catch (err) { - console.log(err); + console.error(err); return false; } } @@ -159,7 +159,7 @@ async function tryReadImage(imgPath, crop) { } // If it's an unsupported type of image (APNG) - just read the file as buffer catch (error) { - console.log(`Failed to read image: ${imgPath}`, error); + console.error(`Failed to read image: ${imgPath}`, error); return fs.readFileSync(imgPath); } } @@ -222,12 +222,12 @@ const processCharacter = async (item, directories) => { return character; } catch (err) { - console.log(`Could not process character: ${item}`); + console.error(`Could not process character: ${item}`); if (err instanceof SyntaxError) { - console.log(`${item} does not contain a valid JSON object.`); + console.error(`${item} does not contain a valid JSON object.`); } else { - console.log('An unexpected error occurred: ', err); + console.error('An unexpected error occurred: ', err); } return { @@ -315,7 +315,7 @@ function readFromV2(char) { }; _.forEach(fieldMappings, (v2Path, charField) => { - //console.log(`Migrating field: ${charField} from ${v2Path}`); + //console.info(`Migrating field: ${charField} from ${v2Path}`); const v2Value = _.get(char.data, v2Path); if (_.isUndefined(v2Value)) { let defaultValue = undefined; @@ -330,15 +330,15 @@ function readFromV2(char) { } if (!_.isUndefined(defaultValue)) { - //console.debug(`Spec v2 extension data missing for field: ${charField}, using default value: ${defaultValue}`); + //console.warn(`Spec v2 extension data missing for field: ${charField}, using default value: ${defaultValue}`); char[charField] = defaultValue; } else { - console.debug(`Char ${char['name']} has Spec v2 data missing for unknown field: ${charField}`); + console.warn(`Char ${char['name']} has Spec v2 data missing for unknown field: ${charField}`); return; } } if (!_.isUndefined(char[charField]) && !_.isUndefined(v2Value) && String(char[charField]) !== String(v2Value)) { - console.debug(`Char ${char['name']} has Spec v2 data mismatch with Spec v1 for field: ${charField}`, char[charField], v2Value); + console.warn(`Char ${char['name']} has Spec v2 data mismatch with Spec v1 for field: ${charField}`, char[charField], v2Value); } char[charField] = v2Value; }); @@ -435,7 +435,7 @@ function charaFormatData(data, directories) { } } catch { - console.debug(`Failed to read world info file: ${data.world}. Character book will not be available.`); + console.warn(`Failed to read world info file: ${data.world}. Character book will not be available.`); } } @@ -445,7 +445,7 @@ function charaFormatData(data, directories) { // Deep merge the extensions object _.set(char, 'data.extensions', deepMerge(char.data.extensions, extensions)); } catch { - console.debug(`Failed to parse extensions JSON: ${data.extensions}`); + console.warn(`Failed to parse extensions JSON: ${data.extensions}`); } } @@ -519,7 +519,7 @@ async function importFromYaml(uploadPath, context, preservedFileName) { const fileText = fs.readFileSync(uploadPath, 'utf8'); fs.rmSync(uploadPath); const yamlData = yaml.parse(fileText); - console.log('Importing from YAML'); + console.info('Importing from YAML'); yamlData.name = sanitize(yamlData.name); const fileName = preservedFileName || getPngName(yamlData.name, context.request.user.directories); let char = convertToV2({ @@ -552,7 +552,7 @@ async function importFromYaml(uploadPath, context, preservedFileName) { async function importFromCharX(uploadPath, { request }, preservedFileName) { const data = fs.readFileSync(uploadPath).buffer; fs.rmSync(uploadPath); - console.log('Importing from CharX'); + console.info('Importing from CharX'); const cardBuffer = await extractFileFromZipBuffer(data, 'card.json'); if (!cardBuffer) { @@ -601,7 +601,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) { let jsonData = JSON.parse(data); if (jsonData.spec !== undefined) { - console.log(`Importing from ${jsonData.spec} json`); + console.info(`Importing from ${jsonData.spec} json`); importRisuSprites(request.user.directories, jsonData); unsetFavFlag(jsonData); jsonData = readFromV2(jsonData); @@ -611,7 +611,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) { const result = await writeCharacterData(defaultAvatarPath, char, pngName, request); return result ? pngName : ''; } else if (jsonData.name !== undefined) { - console.log('Importing from v1 json'); + console.info('Importing from v1 json'); jsonData.name = sanitize(jsonData.name); if (jsonData.creator_notes) { jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); @@ -637,7 +637,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) { const result = await writeCharacterData(defaultAvatarPath, charJSON, pngName, request); return result ? pngName : ''; } else if (jsonData.char_name !== undefined) {//json Pygmalion notepad - console.log('Importing from gradio json'); + console.info('Importing from gradio json'); jsonData.char_name = sanitize(jsonData.char_name); if (jsonData.creator_notes) { jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); @@ -684,7 +684,7 @@ async function importFromPng(uploadPath, { request }, preservedFileName) { const pngName = preservedFileName || getPngName(jsonData.name, request.user.directories); if (jsonData.spec !== undefined) { - console.log(`Found a ${jsonData.spec} character file.`); + console.info(`Found a ${jsonData.spec} character file.`); importRisuSprites(request.user.directories, jsonData); unsetFavFlag(jsonData); jsonData = readFromV2(jsonData); @@ -694,7 +694,7 @@ async function importFromPng(uploadPath, { request }, preservedFileName) { fs.unlinkSync(uploadPath); return result ? pngName : ''; } else if (jsonData.name !== undefined) { - console.log('Found a v1 character file.'); + console.info('Found a v1 character file.'); if (jsonData.creator_notes) { jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); @@ -853,7 +853,7 @@ router.post('/edit', urlencodedParser, async function (request, response) { * @returns {void} */ router.post('/edit-attribute', jsonParser, async function (request, response) { - console.log(request.body); + console.debug(request.body); if (!request.body) { console.error('Error: no response body detected'); return response.status(400).send('Error: no response body detected'); @@ -921,7 +921,7 @@ router.post('/merge-attributes', jsonParser, async function (request, response) await writeCharacterData(avatarPath, JSON.stringify(character), targetImg, request); response.sendStatus(200); } else { - console.log(validator.lastValidationError); + console.error(validator.lastValidationError); response.status(400).send({ message: `Validation failed for ${character.name}`, error: validator.lastValidationError }); } } catch (exception) { @@ -1043,7 +1043,7 @@ router.post('/chats', jsonParser, async function (request, response) { const fileSizeInKB = `${(stats.size / 1024).toFixed(2)}kb`; if (stats.size === 0) { - console.log(`Found an empty chat file: ${pathToFile}`); + console.warn(`Found an empty chat file: ${pathToFile}`); res({}); return; } @@ -1075,7 +1075,7 @@ router.post('/chats', jsonParser, async function (request, response) { res(chatData); } else { - console.log('Found an invalid or corrupted chat file:', pathToFile); + console.warn('Found an invalid or corrupted chat file:', pathToFile); res({}); } } @@ -1088,7 +1088,7 @@ router.post('/chats', jsonParser, async function (request, response) { return response.send(validFiles); } catch (error) { - console.log(error); + console.error(error); return response.send({ error: true }); } }); @@ -1155,7 +1155,7 @@ router.post('/import', urlencodedParser, async function (request, response) { response.send({ file_name: fileName }); } catch (err) { - console.log(err); + console.error(err); response.send({ error: true }); } }); @@ -1163,14 +1163,13 @@ router.post('/import', urlencodedParser, async function (request, response) { router.post('/duplicate', jsonParser, async function (request, response) { try { if (!request.body.avatar_url) { - console.log('avatar URL not found in request body'); - console.log(request.body); + console.error('avatar URL not found in request body'); + console.debug(request.body); return response.sendStatus(400); } let filename = path.join(request.user.directories.characters, sanitize(request.body.avatar_url)); if (!fs.existsSync(filename)) { - console.log('file for dupe not found'); - console.log(filename); + console.error('file for dupe not found', filename); return response.sendStatus(404); } let suffix = 1; @@ -1198,7 +1197,7 @@ router.post('/duplicate', jsonParser, async function (request, response) { } fs.copyFileSync(filename, newFilename); - console.log(`${filename} was copied to ${newFilename}`); + console.info(`${filename} was copied to ${newFilename}`); response.send({ path: path.parse(newFilename).base }); } catch (error) { diff --git a/src/endpoints/chats.js b/src/endpoints/chats.js index 62c790400..c4cd6bedc 100644 --- a/src/endpoints/chats.js +++ b/src/endpoints/chats.js @@ -49,7 +49,7 @@ function backupChat(directory, name, chat) { removeOldBackups(directory, 'chat_', maxTotalChatBackups); } catch (err) { - console.log(`Could not backup chat for ${name}`, err); + console.error(`Could not backup chat for ${name}`, err); } } @@ -277,8 +277,8 @@ router.post('/save', jsonParser, function (request, response) { getBackupFunction(request.user.profile.handle)(request.user.directories.backups, directoryName, jsonlData); return response.send({ result: 'ok' }); } catch (error) { - response.send(error); - return console.log(error); + console.error(error); + return response.send(error); } }); @@ -330,17 +330,17 @@ router.post('/rename', jsonParser, async function (request, response) { const pathToOriginalFile = path.join(pathToFolder, sanitize(request.body.original_file)); const pathToRenamedFile = path.join(pathToFolder, sanitize(request.body.renamed_file)); const sanitizedFileName = path.parse(pathToRenamedFile).name; - console.log('Old chat name', pathToOriginalFile); - console.log('New chat name', pathToRenamedFile); + console.info('Old chat name', pathToOriginalFile); + console.info('New chat name', pathToRenamedFile); if (!fs.existsSync(pathToOriginalFile) || fs.existsSync(pathToRenamedFile)) { - console.log('Either Source or Destination files are not available'); + console.error('Either Source or Destination files are not available'); return response.status(400).send({ error: true }); } fs.copyFileSync(pathToOriginalFile, pathToRenamedFile); fs.rmSync(pathToOriginalFile); - console.log('Successfully renamed.'); + console.info('Successfully renamed.'); return response.send({ ok: true, sanitizedFileName }); }); @@ -351,12 +351,12 @@ router.post('/delete', jsonParser, function (request, response) { const chatFileExists = fs.existsSync(filePath); if (!chatFileExists) { - console.log(`Chat file not found '${filePath}'`); + console.error(`Chat file not found '${filePath}'`); return response.sendStatus(400); } fs.rmSync(filePath); - console.log('Deleted chat file: ' + filePath); + console.info(`Deleted chat file: ${filePath}`); return response.send('ok'); }); @@ -373,7 +373,7 @@ router.post('/export', jsonParser, async function (request, response) { const errorMessage = { message: `Could not find JSONL file to export. Source chat file: ${filename}.`, }; - console.log(errorMessage.message); + console.error(errorMessage.message); return response.status(404).json(errorMessage); } try { @@ -386,14 +386,14 @@ router.post('/export', jsonParser, async function (request, response) { result: rawFile, }; - console.log(`Chat exported as ${exportfilename}`); + console.info(`Chat exported as ${exportfilename}`); return response.status(200).json(successMessage); } catch (err) { console.error(err); const errorMessage = { message: `Could not read JSONL file to export. Source chat file: ${filename}.`, }; - console.log(errorMessage.message); + console.error(errorMessage.message); return response.status(500).json(errorMessage); } } @@ -420,12 +420,11 @@ router.post('/export', jsonParser, async function (request, response) { message: `Chat saved to ${exportfilename}`, result: buffer, }; - console.log(`Chat exported as ${exportfilename}`); + console.info(`Chat exported as ${exportfilename}`); return response.status(200).json(successMessage); }); } catch (err) { - console.log('chat export failed.'); - console.log(err); + console.error('chat export failed.', err); return response.sendStatus(400); } }); @@ -482,7 +481,7 @@ router.post('/import', urlencodedParser, function (request, response) { } else if (Array.isArray(jsonData.messages)) { // Agnai's format importFunc = importAgnaiChat; } else { // Unknown format - console.log('Incorrect chat format .json'); + console.error('Incorrect chat format .json'); return response.send({ error: true }); } @@ -510,7 +509,7 @@ router.post('/import', urlencodedParser, function (request, response) { const jsonData = JSON.parse(header); if (!(jsonData.user_name !== undefined || jsonData.name !== undefined)) { - console.log('Incorrect chat format .jsonl'); + console.error('Incorrect chat format .jsonl'); return response.send({ error: true }); } @@ -616,7 +615,7 @@ router.post('/search', jsonParser, function (request, response) { break; } } catch (error) { - console.error(groupFile, 'group file is corrupted:', error); + console.warn(groupFile, 'group file is corrupted:', error); } } diff --git a/src/endpoints/classify.js b/src/endpoints/classify.js index 02c35a161..996704c49 100644 --- a/src/endpoints/classify.js +++ b/src/endpoints/classify.js @@ -44,9 +44,9 @@ router.post('/', jsonParser, async (req, res) => { } } - console.log('Classify input:', text); + console.debug('Classify input:', text); const result = await getResult(text); - console.log('Classify output:', result); + console.debug('Classify output:', result); return res.json({ classification: result }); } catch (error) { diff --git a/src/endpoints/content-manager.js b/src/endpoints/content-manager.js index 9ba251a40..254134362 100644 --- a/src/endpoints/content-manager.js +++ b/src/endpoints/content-manager.js @@ -71,7 +71,7 @@ export function getDefaultPresets(directories) { return presets; } catch (err) { - console.log('Failed to get default presets', err); + console.warn('Failed to get default presets', err); return []; } } @@ -92,7 +92,7 @@ export function getDefaultPresetFile(filename) { const fileContent = fs.readFileSync(contentPath, 'utf8'); return JSON.parse(fileContent); } catch (err) { - console.log(`Failed to get default file ${filename}`, err); + console.warn(`Failed to get default file ${filename}`, err); return null; } } @@ -121,21 +121,21 @@ async function seedContentForUser(contentIndex, directories, forceCategories) { } if (!contentItem.folder) { - console.log(`Content file ${contentItem.filename} has no parent folder`); + console.warn(`Content file ${contentItem.filename} has no parent folder`); continue; } const contentPath = path.join(contentItem.folder, contentItem.filename); if (!fs.existsSync(contentPath)) { - console.log(`Content file ${contentItem.filename} is missing`); + console.warn(`Content file ${contentItem.filename} is missing`); continue; } const contentTarget = getTargetByType(contentItem.type, directories); if (!contentTarget) { - console.log(`Content file ${contentItem.filename} has unknown type ${contentItem.type}`); + console.warn(`Content file ${contentItem.filename} has unknown type ${contentItem.type}`); continue; } @@ -144,12 +144,12 @@ async function seedContentForUser(contentIndex, directories, forceCategories) { contentLog.push(contentItem.filename); if (fs.existsSync(targetPath)) { - console.log(`Content file ${contentItem.filename} already exists in ${contentTarget}`); + console.warn(`Content file ${contentItem.filename} already exists in ${contentTarget}`); continue; } fs.cpSync(contentPath, targetPath, { recursive: true, force: false }); - console.log(`Content file ${contentItem.filename} copied to ${contentTarget}`); + console.info(`Content file ${contentItem.filename} copied to ${contentTarget}`); anyContentAdded = true; } @@ -182,12 +182,12 @@ export async function checkForNewContent(directoriesList, forceCategories = []) } if (anyContentAdded && !contentCheckSkip && forceCategories?.length === 0) { - console.log(); - console.log(`${color.blue('If you don\'t want to receive content updates in the future, set')} ${color.yellow('skipContentCheck')} ${color.blue('to true in the config.yaml file.')}`); - console.log(); + console.info(); + console.info(`${color.blue('If you don\'t want to receive content updates in the future, set')} ${color.yellow('skipContentCheck')} ${color.blue('to true in the config.yaml file.')}`); + console.info(); } } catch (err) { - console.log('Content check failed', err); + console.error('Content check failed', err); } } @@ -331,7 +331,7 @@ async function downloadChubLorebook(id) { if (!result.ok) { const text = await result.text(); - console.log('Chub returned error', result.statusText, text); + console.error('Chub returned error', result.statusText, text); throw new Error('Failed to download lorebook'); } @@ -355,7 +355,7 @@ async function downloadChubCharacter(id) { if (!result.ok) { const text = await result.text(); - console.log('Chub returned error', result.statusText, text); + console.error('Chub returned error', result.statusText, text); throw new Error('Failed to download character'); } @@ -376,7 +376,7 @@ async function downloadPygmalionCharacter(id) { if (!result.ok) { const text = await result.text(); - console.log('Pygsite returned error', result.status, text); + console.error('Pygsite returned error', result.status, text); throw new Error('Failed to download character'); } @@ -485,7 +485,7 @@ async function downloadJannyCharacter(uuid) { } } - console.log('Janny returned error', result.statusText, await result.text()); + console.error('Janny returned error', result.statusText, await result.text()); throw new Error('Failed to download character'); } @@ -577,7 +577,7 @@ async function downloadRisuCharacter(uuid) { if (!result.ok) { const text = await result.text(); - console.log('RisuAI returned error', result.statusText, text); + console.error('RisuAI returned error', result.statusText, text); throw new Error('Failed to download character'); } @@ -673,11 +673,11 @@ router.post('/importURL', jsonParser, async (request, response) => { type = chubParsed?.type; if (chubParsed?.type === 'character') { - console.log('Downloading chub character:', chubParsed.id); + console.info('Downloading chub character:', chubParsed.id); result = await downloadChubCharacter(chubParsed.id); } else if (chubParsed?.type === 'lorebook') { - console.log('Downloading chub lorebook:', chubParsed.id); + console.info('Downloading chub lorebook:', chubParsed.id); result = await downloadChubLorebook(chubParsed.id); } else { @@ -692,7 +692,7 @@ router.post('/importURL', jsonParser, async (request, response) => { type = 'character'; result = await downloadRisuCharacter(uuid); } else if (isGeneric) { - console.log('Downloading from generic url.'); + console.info('Downloading from generic url.'); type = 'character'; result = await downloadGenericPng(url); } else { @@ -708,7 +708,7 @@ router.post('/importURL', jsonParser, async (request, response) => { response.set('X-Custom-Content-Type', type); return response.send(result.buffer); } catch (error) { - console.log('Importing custom content failed', error); + console.error('Importing custom content failed', error); return response.sendStatus(500); } }); @@ -728,22 +728,22 @@ router.post('/importUUID', jsonParser, async (request, response) => { const uuidType = uuid.includes('lorebook') ? 'lorebook' : 'character'; if (isPygmalion) { - console.log('Downloading Pygmalion character:', uuid); + console.info('Downloading Pygmalion character:', uuid); result = await downloadPygmalionCharacter(uuid); } else if (isJannny) { - console.log('Downloading Janitor character:', uuid.split('_')[0]); + console.info('Downloading Janitor character:', uuid.split('_')[0]); result = await downloadJannyCharacter(uuid.split('_')[0]); } else if (isAICC) { const [, author, card] = uuid.split('/'); - console.log('Downloading AICC character:', `${author}/${card}`); + console.info('Downloading AICC character:', `${author}/${card}`); result = await downloadAICCCharacter(`${author}/${card}`); } else { if (uuidType === 'character') { - console.log('Downloading chub character:', uuid); + console.info('Downloading chub character:', uuid); result = await downloadChubCharacter(uuid); } else if (uuidType === 'lorebook') { - console.log('Downloading chub lorebook:', uuid); + console.info('Downloading chub lorebook:', uuid); result = await downloadChubLorebook(uuid); } else { @@ -756,7 +756,7 @@ router.post('/importUUID', jsonParser, async (request, response) => { response.set('X-Custom-Content-Type', uuidType); return response.send(result.buffer); } catch (error) { - console.log('Importing custom content failed', error); + console.error('Importing custom content failed', error); return response.sendStatus(500); } }); diff --git a/src/endpoints/extensions.js b/src/endpoints/extensions.js index b3b04b32d..9c96065c4 100644 --- a/src/endpoints/extensions.js +++ b/src/endpoints/extensions.js @@ -80,7 +80,7 @@ router.post('/install', jsonParser, async (request, response) => { const { url, global } = request.body; if (global && !request.user.profile.admin) { - console.warn(`User ${request.user.profile.handle} does not have permission to install global extensions.`); + console.error(`User ${request.user.profile.handle} does not have permission to install global extensions.`); return response.status(403).send('Forbidden: No permission to install global extensions.'); } @@ -92,13 +92,13 @@ router.post('/install', jsonParser, async (request, response) => { } await git.clone(url, extensionPath, { '--depth': 1 }); - console.log(`Extension has been cloned at ${extensionPath}`); + console.info(`Extension has been cloned at ${extensionPath}`); const { version, author, display_name } = await getManifest(extensionPath); return response.send({ version, author, display_name, extensionPath }); } catch (error) { - console.log('Importing custom content failed', error); + console.error('Importing custom content failed', error); return response.status(500).send(`Server Error: ${error.message}`); } }); @@ -124,7 +124,7 @@ router.post('/update', jsonParser, async (request, response) => { const { extensionName, global } = request.body; if (global && !request.user.profile.admin) { - console.warn(`User ${request.user.profile.handle} does not have permission to update global extensions.`); + console.error(`User ${request.user.profile.handle} does not have permission to update global extensions.`); return response.status(403).send('Forbidden: No permission to update global extensions.'); } @@ -139,9 +139,9 @@ router.post('/update', jsonParser, async (request, response) => { const currentBranch = await git.cwd(extensionPath).branch(); if (!isUpToDate) { await git.cwd(extensionPath).pull('origin', currentBranch.current); - console.log(`Extension has been updated at ${extensionPath}`); + console.info(`Extension has been updated at ${extensionPath}`); } else { - console.log(`Extension is up to date at ${extensionPath}`); + console.info(`Extension is up to date at ${extensionPath}`); } await git.cwd(extensionPath).fetch('origin'); const fullCommitHash = await git.cwd(extensionPath).revparse(['HEAD']); @@ -150,7 +150,7 @@ router.post('/update', jsonParser, async (request, response) => { return response.send({ shortCommitHash, extensionPath, isUpToDate, remoteUrl }); } catch (error) { - console.log('Updating custom content failed', error); + console.error('Updating custom content failed', error); return response.status(500).send(`Server Error: ${error.message}`); } }); @@ -164,7 +164,7 @@ router.post('/move', jsonParser, async (request, response) => { } if (!request.user.profile.admin) { - console.warn(`User ${request.user.profile.handle} does not have permission to move extensions.`); + console.error(`User ${request.user.profile.handle} does not have permission to move extensions.`); return response.status(403).send('Forbidden: No permission to move extensions.'); } @@ -190,11 +190,11 @@ router.post('/move', jsonParser, async (request, response) => { fs.cpSync(sourcePath, destinationPath, { recursive: true, force: true }); fs.rmSync(sourcePath, { recursive: true, force: true }); - console.log(`Extension has been moved from ${sourcePath} to ${destinationPath}`); + console.info(`Extension has been moved from ${sourcePath} to ${destinationPath}`); return response.sendStatus(204); } catch (error) { - console.log('Moving extension failed', error); + console.error('Moving extension failed', error); return response.status(500).send('Internal Server Error. Try again later.'); } }); @@ -237,13 +237,13 @@ router.post('/version', jsonParser, async (request, response) => { // get only the working branch const currentBranchName = currentBranch.current; await git.cwd(extensionPath).fetch('origin'); - console.log(extensionName, currentBranchName, currentCommitHash); + console.debug(extensionName, currentBranchName, currentCommitHash); const { isUpToDate, remoteUrl } = await checkIfRepoIsUpToDate(extensionPath); return response.send({ currentBranchName, currentCommitHash, isUpToDate, remoteUrl }); } catch (error) { - console.log('Getting extension version failed', error); + console.error('Getting extension version failed', error); return response.status(500).send(`Server Error: ${error.message}`); } }); @@ -265,7 +265,7 @@ router.post('/delete', jsonParser, async (request, response) => { const { extensionName, global } = request.body; if (global && !request.user.profile.admin) { - console.warn(`User ${request.user.profile.handle} does not have permission to delete global extensions.`); + console.error(`User ${request.user.profile.handle} does not have permission to delete global extensions.`); return response.status(403).send('Forbidden: No permission to delete global extensions.'); } @@ -277,12 +277,12 @@ router.post('/delete', jsonParser, async (request, response) => { } await fs.promises.rm(extensionPath, { recursive: true }); - console.log(`Extension has been deleted at ${extensionPath}`); + console.info(`Extension has been deleted at ${extensionPath}`); return response.send(`Extension has been deleted at ${extensionPath}`); } catch (error) { - console.log('Deleting custom content failed', error); + console.error('Deleting custom content failed', error); return response.status(500).send(`Server Error: ${error.message}`); } }); @@ -323,7 +323,7 @@ router.get('/discover', jsonParser, function (request, response) { // Combine all extensions const allExtensions = [...builtInExtensions, ...userExtensions, ...globalExtensions]; - console.log('Extensions available for', request.user.profile.handle, allExtensions); + console.info('Extensions available for', request.user.profile.handle, allExtensions); return response.send(allExtensions); }); diff --git a/src/endpoints/files.js b/src/endpoints/files.js index dd34a4ab6..8ddc8a8f0 100644 --- a/src/endpoints/files.js +++ b/src/endpoints/files.js @@ -21,7 +21,7 @@ router.post('/sanitize-filename', jsonParser, async (request, response) => { const sanitizedFilename = sanitize(fileName); return response.send({ fileName: sanitizedFilename }); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -44,10 +44,10 @@ router.post('/upload', jsonParser, async (request, response) => { const pathToUpload = path.join(request.user.directories.files, request.body.name); writeFileSyncAtomic(pathToUpload, request.body.data, 'base64'); const url = clientRelativePath(request.user.directories.root, pathToUpload); - console.log(`Uploaded file: ${url} from ${request.user.profile.handle}`); + console.info(`Uploaded file: ${url} from ${request.user.profile.handle}`); return response.send({ path: url }); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -68,10 +68,10 @@ router.post('/delete', jsonParser, async (request, response) => { } fs.rmSync(pathToDelete); - console.log(`Deleted file: ${request.body.path} from ${request.user.profile.handle}`); + console.info(`Deleted file: ${request.body.path} from ${request.user.profile.handle}`); return response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -87,7 +87,7 @@ router.post('/verify', jsonParser, async (request, response) => { for (const url of request.body.urls) { const pathToVerify = path.join(request.user.directories.root, url); if (!pathToVerify.startsWith(request.user.directories.files)) { - console.debug(`File verification: Invalid path: ${pathToVerify}`); + console.warn(`File verification: Invalid path: ${pathToVerify}`); continue; } const fileExists = fs.existsSync(pathToVerify); @@ -96,7 +96,7 @@ router.post('/verify', jsonParser, async (request, response) => { return response.send(verified); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); diff --git a/src/endpoints/google.js b/src/endpoints/google.js index c9b6c6956..8882a9914 100644 --- a/src/endpoints/google.js +++ b/src/endpoints/google.js @@ -34,7 +34,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { generationConfig: { maxOutputTokens: 1000 }, }; - console.log('Multimodal captioning request', model, body); + console.debug('Multimodal captioning request', model, body); const result = await fetch(url, { body: JSON.stringify(body), @@ -46,13 +46,13 @@ router.post('/caption-image', jsonParser, async (request, response) => { if (!result.ok) { const error = await result.json(); - console.log(`Google AI Studio API returned error: ${result.status} ${result.statusText}`, error); + console.error(`Google AI Studio API returned error: ${result.status} ${result.statusText}`, error); return response.status(result.status).send({ error: true }); } /** @type {any} */ const data = await result.json(); - console.log('Multimodal captioning response', data); + console.debug('Multimodal captioning response', data); const candidates = data?.candidates; if (!candidates) { diff --git a/src/endpoints/groups.js b/src/endpoints/groups.js index fb2e51d75..e700233d8 100644 --- a/src/endpoints/groups.js +++ b/src/endpoints/groups.js @@ -114,7 +114,7 @@ router.post('/delete', jsonParser, async (request, response) => { if (group && Array.isArray(group.chats)) { for (const chat of group.chats) { - console.log('Deleting group chat', chat); + console.info('Deleting group chat', chat); const pathToFile = path.join(request.user.directories.groupChats, `${id}.jsonl`); if (fs.existsSync(pathToFile)) { diff --git a/src/endpoints/horde.js b/src/endpoints/horde.js index cd42bdb96..b8d082af9 100644 --- a/src/endpoints/horde.js +++ b/src/endpoints/horde.js @@ -155,7 +155,7 @@ router.post('/cancel-task', jsonParser, async (request, response) => { }); const data = await fetchResult.json(); - console.log(`Cancelled Horde task ${taskId}`); + console.info(`Cancelled Horde task ${taskId}`); return response.send(data); } catch (error) { console.error(error); @@ -174,7 +174,7 @@ router.post('/task-status', jsonParser, async (request, response) => { }); const data = await fetchResult.json(); - console.log(`Horde task ${taskId} status:`, data); + console.info(`Horde task ${taskId} status:`, data); return response.send(data); } catch (error) { console.error(error); @@ -187,7 +187,7 @@ router.post('/generate-text', jsonParser, async (request, response) => { const url = 'https://aihorde.net/api/v2/generate/text/async'; const agent = await getClientAgent(); - console.log(request.body); + console.debug(request.body); try { const result = await fetch(url, { method: 'POST', @@ -201,14 +201,14 @@ router.post('/generate-text', jsonParser, async (request, response) => { if (!result.ok) { const message = await result.text(); - console.log('Horde returned an error:', message); + console.error('Horde returned an error:', message); return response.send({ error: { message } }); } const data = await result.json(); return response.send(data); } catch (error) { - console.log(error); + console.error(error); return response.send({ error: true }); } }); @@ -254,7 +254,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { await delay(CHECK_INTERVAL); const status = await ai_horde.getInterrogationStatus(result.id); - console.log(status); + console.info(status); if (status.state === HordeAsyncRequestStates.done) { @@ -263,7 +263,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { return response.sendStatus(500); } - console.log('Image interrogation result:', status); + console.debug('Image interrogation result:', status); const caption = status?.forms[0]?.result?.caption || ''; if (!caption) { @@ -275,7 +275,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { } if (status.state === HordeAsyncRequestStates.faulted || status.state === HordeAsyncRequestStates.cancelled) { - console.log('Image interrogation request is not successful.'); + console.error('Image interrogation request is not successful.'); return response.sendStatus(503); } } @@ -315,7 +315,7 @@ router.post('/generate-image', jsonParser, async (request, response) => { try { const maxLength = PROMPT_THRESHOLD - String(request.body.negative_prompt).length - 5; if (String(request.body.prompt).length > maxLength) { - console.log('Stable Horde prompt is too long, truncating...'); + console.warn('Stable Horde prompt is too long, truncating...'); request.body.prompt = String(request.body.prompt).substring(0, maxLength); } @@ -324,14 +324,14 @@ router.post('/generate-image', jsonParser, async (request, response) => { const sanitized = sanitizeHordeImagePrompt(request.body.prompt); if (request.body.prompt !== sanitized) { - console.log('Stable Horde prompt was sanitized.'); + console.info('Stable Horde prompt was sanitized.'); } request.body.prompt = sanitized; } const api_key_horde = readSecret(request.user.directories, SECRET_KEYS.HORDE) || ANONYMOUS_KEY; - console.log('Stable Horde request:', request.body); + console.debug('Stable Horde request:', request.body); const ai_horde = await getHordeClient(); // noinspection JSCheckFunctionSignatures -- see @ts-ignore - use_gfpgan @@ -364,12 +364,12 @@ router.post('/generate-image', jsonParser, async (request, response) => { return response.sendStatus(400); } - console.log('Horde image generation request:', generation); + console.debug('Horde image generation request:', generation); const controller = new AbortController(); request.socket.removeAllListeners('close'); request.socket.on('close', function () { - console.log('Horde image generation request aborted.'); + console.info('Horde image generation request aborted.'); controller.abort(); if (generation.id) ai_horde.deleteImageGenerationRequest(generation.id); }); @@ -378,7 +378,7 @@ router.post('/generate-image', jsonParser, async (request, response) => { controller.signal.throwIfAborted(); await delay(CHECK_INTERVAL); const check = await ai_horde.getImageGenerationCheck(generation.id); - console.log(check); + console.info(check); if (check.done) { const result = await ai_horde.getImageGenerationStatus(generation.id); diff --git a/src/endpoints/images.js b/src/endpoints/images.js index 22c1d5b17..c1cf3c7c1 100644 --- a/src/endpoints/images.js +++ b/src/endpoints/images.js @@ -71,7 +71,7 @@ router.post('/upload', jsonParser, async (request, response) => { await fs.promises.writeFile(pathToNewFile, new Uint8Array(imageBuffer)); response.send({ path: clientRelativePath(request.user.directories.root, pathToNewFile) }); } catch (error) { - console.log(error); + console.error(error); response.status(500).send({ error: 'Failed to save the image' }); } }); diff --git a/src/endpoints/novelai.js b/src/endpoints/novelai.js index 9629aad40..bfed0a323 100644 --- a/src/endpoints/novelai.js +++ b/src/endpoints/novelai.js @@ -120,7 +120,7 @@ router.post('/status', jsonParser, async function (req, res) { const api_key_novel = readSecret(req.user.directories, SECRET_KEYS.NOVEL); if (!api_key_novel) { - console.log('NovelAI Access Token is missing.'); + console.error('NovelAI Access Token is missing.'); return res.sendStatus(400); } @@ -137,15 +137,15 @@ router.post('/status', jsonParser, async function (req, res) { const data = await response.json(); return res.send(data); } else if (response.status == 401) { - console.log('NovelAI Access Token is incorrect.'); + console.error('NovelAI Access Token is incorrect.'); return res.send({ error: true }); } else { - console.log('NovelAI returned an error:', response.statusText); + console.error('NovelAI returned an error:', response.statusText); return res.send({ error: true }); } } catch (error) { - console.log(error); + console.error(error); return res.send({ error: true }); } }); @@ -156,7 +156,7 @@ router.post('/generate', jsonParser, async function (req, res) { const api_key_novel = readSecret(req.user.directories, SECRET_KEYS.NOVEL); if (!api_key_novel) { - console.log('NovelAI Access Token is missing.'); + console.error('NovelAI Access Token is missing.'); return res.sendStatus(400); } @@ -241,7 +241,7 @@ router.post('/generate', jsonParser, async function (req, res) { } } - console.log(util.inspect(data, { depth: 4 })); + console.debug(util.inspect(data, { depth: 4 })); const args = { body: JSON.stringify(data), @@ -261,7 +261,7 @@ router.post('/generate', jsonParser, async function (req, res) { if (!response.ok) { const text = await response.text(); let message = text; - console.log(`Novel API returned error: ${response.status} ${response.statusText} ${text}`); + console.error(`Novel API returned error: ${response.status} ${response.statusText} ${text}`); try { const data = JSON.parse(text); @@ -276,7 +276,7 @@ router.post('/generate', jsonParser, async function (req, res) { /** @type {any} */ const data = await response.json(); - console.log('NovelAI Output', data?.output); + console.debug('NovelAI Output', data?.output); return res.send(data); } } catch (error) { @@ -292,12 +292,12 @@ router.post('/generate-image', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.NOVEL); if (!key) { - console.log('NovelAI Access Token is missing.'); + console.error('NovelAI Access Token is missing.'); return response.sendStatus(400); } try { - console.log('NAI Diffusion request:', request.body); + console.debug('NAI Diffusion request:', request.body); const generateUrl = `${IMAGE_NOVELAI}/ai/generate-image`; const generateResult = await fetch(generateUrl, { method: 'POST', @@ -358,7 +358,7 @@ router.post('/generate-image', jsonParser, async (request, response) => { if (!generateResult.ok) { const text = await generateResult.text(); - console.log('NovelAI returned an error.', generateResult.statusText, text); + console.error('NovelAI returned an error.', generateResult.statusText, text); return response.sendStatus(500); } @@ -366,7 +366,7 @@ router.post('/generate-image', jsonParser, async (request, response) => { const imageBuffer = await extractFileFromZipBuffer(archiveBuffer, '.png'); if (!imageBuffer) { - console.warn('NovelAI generated an image, but the PNG file was not found.'); + console.error('NovelAI generated an image, but the PNG file was not found.'); return response.sendStatus(500); } @@ -378,7 +378,7 @@ router.post('/generate-image', jsonParser, async (request, response) => { } try { - console.debug('Upscaling image...'); + console.info('Upscaling image...'); const upscaleUrl = `${API_NOVELAI}/ai/upscale`; const upscaleResult = await fetch(upscaleUrl, { method: 'POST', @@ -413,7 +413,7 @@ router.post('/generate-image', jsonParser, async (request, response) => { return response.send(originalBase64); } } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -422,7 +422,7 @@ router.post('/generate-voice', jsonParser, async (request, response) => { const token = readSecret(request.user.directories, SECRET_KEYS.NOVEL); if (!token) { - console.log('NovelAI Access Token is missing.'); + console.error('NovelAI Access Token is missing.'); return response.sendStatus(400); } @@ -445,7 +445,7 @@ router.post('/generate-voice', jsonParser, async (request, response) => { if (!result.ok) { const errorText = await result.text(); - console.log('NovelAI returned an error.', result.statusText, errorText); + console.error('NovelAI returned an error.', result.statusText, errorText); return response.sendStatus(500); } diff --git a/src/endpoints/openai.js b/src/endpoints/openai.js index 8c820dc55..5bc140271 100644 --- a/src/endpoints/openai.js +++ b/src/endpoints/openai.js @@ -63,7 +63,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { } if (!key && !request.body.reverse_proxy && ['custom', 'ooba', 'koboldcpp', 'vllm'].includes(request.body.api) === false) { - console.log('No key found for API', request.body.api); + console.error('No key found for API', request.body.api); return response.sendStatus(400); } @@ -93,7 +93,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { excludeKeysByYaml(body, request.body.custom_exclude_body); } - console.log('Multimodal captioning request', body); + console.error('Multimodal captioning request', body); let apiUrl = ''; @@ -158,13 +158,13 @@ router.post('/caption-image', jsonParser, async (request, response) => { if (!result.ok) { const text = await result.text(); - console.log('Multimodal captioning request failed', result.statusText, text); + console.error('Multimodal captioning request failed', result.statusText, text); return response.status(500).send(text); } /** @type {any} */ const data = await result.json(); - console.log('Multimodal captioning response', data); + console.debug('Multimodal captioning response', data); const caption = data?.choices[0]?.message?.content; if (!caption) { @@ -184,17 +184,17 @@ router.post('/transcribe-audio', urlencodedParser, async (request, response) => const key = readSecret(request.user.directories, SECRET_KEYS.OPENAI); if (!key) { - console.log('No OpenAI key found'); + console.error('No OpenAI key found'); return response.sendStatus(400); } if (!request.file) { - console.log('No audio file found'); + console.error('No audio file found'); return response.sendStatus(400); } const formData = new FormData(); - console.log('Processing audio file', request.file.path); + console.info('Processing audio file', request.file.path); formData.append('file', fs.createReadStream(request.file.path), { filename: 'audio.wav', contentType: 'audio/wav' }); formData.append('model', request.body.model); @@ -213,13 +213,13 @@ router.post('/transcribe-audio', urlencodedParser, async (request, response) => if (!result.ok) { const text = await result.text(); - console.log('OpenAI request failed', result.statusText, text); + console.error('OpenAI request failed', result.statusText, text); return response.status(500).send(text); } fs.rmSync(request.file.path); const data = await result.json(); - console.log('OpenAI transcription response', data); + console.debug('OpenAI transcription response', data); return response.json(data); } catch (error) { console.error('OpenAI transcription failed', error); @@ -232,7 +232,7 @@ router.post('/generate-voice', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.OPENAI); if (!key) { - console.log('No OpenAI key found'); + console.error('No OpenAI key found'); return response.sendStatus(400); } @@ -253,7 +253,7 @@ router.post('/generate-voice', jsonParser, async (request, response) => { if (!result.ok) { const text = await result.text(); - console.log('OpenAI request failed', result.statusText, text); + console.error('OpenAI request failed', result.statusText, text); return response.status(500).send(text); } @@ -271,11 +271,11 @@ router.post('/generate-image', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.OPENAI); if (!key) { - console.log('No OpenAI key found'); + console.error('No OpenAI key found'); return response.sendStatus(400); } - console.log('OpenAI request', request.body); + console.debug('OpenAI request', request.body); const result = await fetch('https://api.openai.com/v1/images/generations', { method: 'POST', @@ -288,7 +288,7 @@ router.post('/generate-image', jsonParser, async (request, response) => { if (!result.ok) { const text = await result.text(); - console.log('OpenAI request failed', result.statusText, text); + console.error('OpenAI request failed', result.statusText, text); return response.status(500).send(text); } @@ -308,7 +308,7 @@ custom.post('/generate-voice', jsonParser, async (request, response) => { const { input, provider_endpoint, response_format, voice, speed, model } = request.body; if (!provider_endpoint) { - console.log('No OpenAI-compatible TTS provider endpoint provided'); + console.error('No OpenAI-compatible TTS provider endpoint provided'); return response.sendStatus(400); } @@ -329,7 +329,7 @@ custom.post('/generate-voice', jsonParser, async (request, response) => { if (!result.ok) { const text = await result.text(); - console.log('OpenAI request failed', result.statusText, text); + console.error('OpenAI request failed', result.statusText, text); return response.status(500).send(text); } diff --git a/src/endpoints/presets.js b/src/endpoints/presets.js index fc7f72cb3..55515551f 100644 --- a/src/endpoints/presets.js +++ b/src/endpoints/presets.js @@ -96,7 +96,7 @@ router.post('/restore', jsonParser, function (request, response) { return response.send(result); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); diff --git a/src/endpoints/search.js b/src/endpoints/search.js index e29e53008..36c2f29ff 100644 --- a/src/endpoints/search.js +++ b/src/endpoints/search.js @@ -94,25 +94,25 @@ router.post('/serpapi', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.SERPAPI); if (!key) { - console.log('No SerpApi key found'); + console.error('No SerpApi key found'); return response.sendStatus(400); } const { query } = request.body; const result = await fetch(`https://serpapi.com/search.json?q=${encodeURIComponent(query)}&api_key=${key}`); - console.log('SerpApi query', query); + console.debug('SerpApi query', query); if (!result.ok) { const text = await result.text(); - console.log('SerpApi request failed', result.statusText, text); + console.error('SerpApi request failed', result.statusText, text); return response.status(500).send(text); } const data = await result.json(); return response.json(data); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -128,7 +128,7 @@ router.post('/transcript', jsonParser, async (request, response) => { const json = request.body.json; if (!id) { - console.log('Id is required for /transcript'); + console.error('Id is required for /transcript'); return response.sendStatus(400); } @@ -153,7 +153,7 @@ router.post('/transcript', jsonParser, async (request, response) => { throw error; } } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -163,17 +163,17 @@ router.post('/searxng', jsonParser, async (request, response) => { const { baseUrl, query, preferences } = request.body; if (!baseUrl || !query) { - console.log('Missing required parameters for /searxng'); + console.error('Missing required parameters for /searxng'); return response.sendStatus(400); } - console.log('SearXNG query', baseUrl, query); + console.debug('SearXNG query', baseUrl, query); const mainPageUrl = new URL(baseUrl); const mainPageRequest = await fetch(mainPageUrl, { headers: visitHeaders }); if (!mainPageRequest.ok) { - console.log('SearXNG request failed', mainPageRequest.statusText); + console.error('SearXNG request failed', mainPageRequest.statusText); return response.sendStatus(500); } @@ -197,14 +197,14 @@ router.post('/searxng', jsonParser, async (request, response) => { if (!searchResult.ok) { const text = await searchResult.text(); - console.log('SearXNG request failed', searchResult.statusText, text); + console.error('SearXNG request failed', searchResult.statusText, text); return response.sendStatus(500); } const data = await searchResult.text(); return response.send(data); } catch (error) { - console.log('SearXNG request failed', error); + console.error('SearXNG request failed', error); return response.sendStatus(500); } }); @@ -214,7 +214,7 @@ router.post('/tavily', jsonParser, async (request, response) => { const apiKey = readSecret(request.user.directories, SECRET_KEYS.TAVILY); if (!apiKey) { - console.log('No Tavily key found'); + console.error('No Tavily key found'); return response.sendStatus(400); } @@ -241,18 +241,18 @@ router.post('/tavily', jsonParser, async (request, response) => { body: JSON.stringify(body), }); - console.log('Tavily query', query); + console.debug('Tavily query', query); if (!result.ok) { const text = await result.text(); - console.log('Tavily request failed', result.statusText, text); + console.error('Tavily request failed', result.statusText, text); return response.status(500).send(text); } const data = await result.json(); return response.json(data); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -262,7 +262,7 @@ router.post('/visit', jsonParser, async (request, response) => { const url = request.body.url; if (!url) { - console.log('No url provided for /visit'); + console.error('No url provided for /visit'); return response.sendStatus(400); } @@ -289,29 +289,29 @@ router.post('/visit', jsonParser, async (request, response) => { throw new Error('Invalid hostname'); } } catch (error) { - console.log('Invalid url provided for /visit', url); + console.error('Invalid url provided for /visit', url); return response.sendStatus(400); } - console.log('Visiting web URL', url); + console.info('Visiting web URL', url); const result = await fetch(url, { headers: visitHeaders }); if (!result.ok) { - console.log(`Visit failed ${result.status} ${result.statusText}`); + console.error(`Visit failed ${result.status} ${result.statusText}`); return response.sendStatus(500); } const contentType = String(result.headers.get('content-type')); if (!contentType.includes('text/html')) { - console.log(`Visit failed, content-type is ${contentType}, expected text/html`); + console.error(`Visit failed, content-type is ${contentType}, expected text/html`); return response.sendStatus(500); } const text = await result.text(); return response.send(text); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); diff --git a/src/endpoints/secrets.js b/src/endpoints/secrets.js index 4287b3cba..e7ff40fd4 100644 --- a/src/endpoints/secrets.js +++ b/src/endpoints/secrets.js @@ -151,7 +151,7 @@ export function getAllSecrets(directories) { const filePath = path.join(directories.root, SECRETS_FILE); if (!fs.existsSync(filePath)) { - console.log('Secrets file does not exist'); + console.error('Secrets file does not exist'); return undefined; } diff --git a/src/endpoints/settings.js b/src/endpoints/settings.js index 0c4a7cf28..195095d90 100644 --- a/src/endpoints/settings.js +++ b/src/endpoints/settings.js @@ -104,7 +104,7 @@ function readPresetsFromDirectory(directoryPath, options = {}) { fileNames.push(removeFileExtension ? item.replace(/\.[^/.]+$/, '') : item); } catch { // skip - console.log(`${item} is not a valid JSON`); + console.warn(`${item} is not a valid JSON`); } }); @@ -119,7 +119,7 @@ async function backupSettings() { backupUserSettings(handle, true); } } catch (err) { - console.log('Could not backup settings file', err); + console.error('Could not backup settings file', err); } } @@ -201,7 +201,7 @@ router.post('/save', jsonParser, function (request, response) { triggerAutoSave(request.user.profile.handle); response.send({ result: 'ok' }); } catch (err) { - console.log(err); + console.error(err); response.send(err); } }); @@ -291,7 +291,7 @@ router.post('/get-snapshots', jsonParser, async (request, response) => { response.json(result); } catch (error) { - console.log(error); + console.error(error); response.sendStatus(500); } }); @@ -315,7 +315,7 @@ router.post('/load-snapshot', jsonParser, async (request, response) => { response.send(content); } catch (error) { - console.log(error); + console.error(error); response.sendStatus(500); } }); @@ -325,7 +325,7 @@ router.post('/make-snapshot', jsonParser, async (request, response) => { backupUserSettings(request.user.profile.handle, false); response.sendStatus(204); } catch (error) { - console.log(error); + console.error(error); response.sendStatus(500); } }); @@ -351,7 +351,7 @@ router.post('/restore-snapshot', jsonParser, async (request, response) => { response.sendStatus(204); } catch (error) { - console.log(error); + console.error(error); response.sendStatus(500); } }); diff --git a/src/endpoints/speech.js b/src/endpoints/speech.js index 1f6514a59..3915f6402 100644 --- a/src/endpoints/speech.js +++ b/src/endpoints/speech.js @@ -43,8 +43,8 @@ router.post('/recognize', jsonParser, async (req, res) => { const start = performance.now(); const result = await pipe(wav, { language: lang || null, task: 'transcribe' }); const end = performance.now(); - console.log(`Execution duration: ${(end - start) / 1000} seconds`); - console.log('Transcribed audio:', result.text); + console.debug(`Execution duration: ${(end - start) / 1000} seconds`); + console.debug('Transcribed audio:', result.text); return res.json({ text: result.text }); } catch (error) { @@ -64,7 +64,7 @@ router.post('/synthesize', jsonParser, async (req, res) => { const start = performance.now(); const result = await pipe(text, { speaker_embeddings: speaker_embeddings }); const end = performance.now(); - console.log(`Execution duration: ${(end - start) / 1000} seconds`); + console.debug(`Execution duration: ${(end - start) / 1000} seconds`); const wav = new wavefile.WaveFile(); wav.fromScratch(1, result.sampling_rate, '32f', result.audio); diff --git a/src/endpoints/sprites.js b/src/endpoints/sprites.js index 6a2e5e6b9..81d6fb0c8 100644 --- a/src/endpoints/sprites.js +++ b/src/endpoints/sprites.js @@ -82,14 +82,14 @@ export function importRisuSprites(directories, data) { return; } - console.log(`RisuAI: Found ${images.length} sprites for ${name}. Writing to disk.`); + console.info(`RisuAI: Found ${images.length} sprites for ${name}. Writing to disk.`); const files = fs.readdirSync(spritesPath); outer: for (const [label, fileBase64] of images) { // Remove existing sprite with the same label for (const file of files) { if (path.parse(file).name === label) { - console.log(`RisuAI: The sprite ${label} for ${name} already exists. Skipping.`); + console.warn(`RisuAI: The sprite ${label} for ${name} already exists. Skipping.`); continue outer; } } @@ -133,7 +133,7 @@ router.get('/get', jsonParser, function (request, response) { } } catch (err) { - console.log(err); + console.error(err); } return response.send(sprites); }); diff --git a/src/endpoints/stable-diffusion.js b/src/endpoints/stable-diffusion.js index 94e64d1fd..50fcf63b8 100644 --- a/src/endpoints/stable-diffusion.js +++ b/src/endpoints/stable-diffusion.js @@ -45,7 +45,7 @@ router.post('/ping', jsonParser, async (request, response) => { return response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -99,7 +99,7 @@ router.post('/upscalers', jsonParser, async (request, response) => { return response.send(upscalers); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -131,7 +131,7 @@ router.post('/vaes', jsonParser, async (request, response) => { const names = data.map(x => x.model_name); return response.send(names); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -158,7 +158,7 @@ router.post('/samplers', jsonParser, async (request, response) => { return response.send(names); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -184,7 +184,7 @@ router.post('/schedulers', jsonParser, async (request, response) => { const names = data.map(x => x.name); return response.send(names); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -210,7 +210,7 @@ router.post('/models', jsonParser, async (request, response) => { const models = data.map(x => ({ value: x.title, text: x.title })); return response.send(models); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -230,7 +230,7 @@ router.post('/get-model', jsonParser, async (request, response) => { const data = await result.json(); return response.send(data['sd_model_checkpoint']); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -283,13 +283,13 @@ router.post('/set-model', jsonParser, async (request, response) => { break; } - console.log(`Waiting for SD WebUI to finish model loading... Progress: ${progress}; Job count: ${jobCount}`); + console.info(`Waiting for SD WebUI to finish model loading... Progress: ${progress}; Job count: ${jobCount}`); await delay(CHECK_INTERVAL); } return response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -309,7 +309,7 @@ router.post('/generate', jsonParser, async (request, response) => { } } } catch (error) { - console.log('SD WebUI failed to get options:', error); + console.error('SD WebUI failed to get options:', error); } const controller = new AbortController(); @@ -323,7 +323,7 @@ router.post('/generate', jsonParser, async (request, response) => { controller.abort(); }); - console.log('SD WebUI request:', request.body); + console.debug('SD WebUI request:', request.body); const txt2imgUrl = new URL(request.body.url); txt2imgUrl.pathname = '/sdapi/v1/txt2img'; const result = await fetch(txt2imgUrl, { @@ -344,7 +344,7 @@ router.post('/generate', jsonParser, async (request, response) => { const data = await result.json(); return response.send(data); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -377,7 +377,7 @@ router.post('/sd-next/upscalers', jsonParser, async (request, response) => { return response.send(names); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -395,7 +395,7 @@ comfy.post('/ping', jsonParser, async (request, response) => { return response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -413,7 +413,7 @@ comfy.post('/samplers', jsonParser, async (request, response) => { const data = await result.json(); return response.send(data.KSampler.input.required.sampler_name[0]); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -441,7 +441,7 @@ comfy.post('/models', jsonParser, async (request, response) => { return response.send(models); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -459,7 +459,7 @@ comfy.post('/schedulers', jsonParser, async (request, response) => { const data = await result.json(); return response.send(data.KSampler.input.required.scheduler[0]); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -477,7 +477,7 @@ comfy.post('/vaes', jsonParser, async (request, response) => { const data = await result.json(); return response.send(data.VAELoader.input.required.vae_name[0]); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -487,7 +487,7 @@ comfy.post('/workflows', jsonParser, async (request, response) => { const data = getComfyWorkflows(request.user.directories); return response.send(data); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -501,7 +501,7 @@ comfy.post('/workflow', jsonParser, async (request, response) => { const data = fs.readFileSync(filePath, { encoding: 'utf-8' }); return response.send(JSON.stringify(data)); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -513,7 +513,7 @@ comfy.post('/save-workflow', jsonParser, async (request, response) => { const data = getComfyWorkflows(request.user.directories); return response.send(data); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -526,7 +526,7 @@ comfy.post('/delete-workflow', jsonParser, async (request, response) => { } return response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -591,7 +591,7 @@ comfy.post('/generate', jsonParser, async (request, response) => { const imgBuffer = await imgResponse.arrayBuffer(); return response.send(Buffer.from(imgBuffer).toString('base64')); } catch (error) { - console.log('ComfyUI error:', error); + console.error('ComfyUI error:', error); response.status(500).send(error.message); return response; } @@ -604,7 +604,7 @@ together.post('/models', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.TOGETHERAI); if (!key) { - console.log('TogetherAI key not found.'); + console.error('TogetherAI key not found.'); return response.sendStatus(400); } @@ -616,14 +616,14 @@ together.post('/models', jsonParser, async (request, response) => { }); if (!modelsResponse.ok) { - console.log('TogetherAI returned an error.'); + console.error('TogetherAI returned an error.'); return response.sendStatus(500); } const data = await modelsResponse.json(); if (!Array.isArray(data)) { - console.log('TogetherAI returned invalid data.'); + console.error('TogetherAI returned invalid data.'); return response.sendStatus(500); } @@ -633,7 +633,7 @@ together.post('/models', jsonParser, async (request, response) => { return response.send(models); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -643,11 +643,11 @@ together.post('/generate', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.TOGETHERAI); if (!key) { - console.log('TogetherAI key not found.'); + console.error('TogetherAI key not found.'); return response.sendStatus(400); } - console.log('TogetherAI request:', request.body); + console.debug('TogetherAI request:', request.body); const result = await fetch('https://api.together.xyz/v1/images/generations', { method: 'POST', @@ -669,13 +669,13 @@ together.post('/generate', jsonParser, async (request, response) => { }); if (!result.ok) { - console.log('TogetherAI returned an error.', { body: await result.text() }); + console.error('TogetherAI returned an error.', { body: await result.text() }); return response.sendStatus(500); } /** @type {any} */ const data = await result.json(); - console.log('TogetherAI response:', data); + console.debug('TogetherAI response:', data); const choice = data?.data?.[0]; let b64_json = choice.b64_json; @@ -687,7 +687,7 @@ together.post('/generate', jsonParser, async (request, response) => { return response.send({ format: 'jpg', data: b64_json }); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -709,7 +709,7 @@ drawthings.post('/ping', jsonParser, async (request, response) => { return response.sendStatus(200); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -728,7 +728,7 @@ drawthings.post('/get-model', jsonParser, async (request, response) => { return response.send(data['model']); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -747,14 +747,14 @@ drawthings.post('/get-upscaler', jsonParser, async (request, response) => { return response.send(data['upscaler']); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); drawthings.post('/generate', jsonParser, async (request, response) => { try { - console.log('SD DrawThings API request:', request.body); + console.debug('SD DrawThings API request:', request.body); const url = new URL(request.body.url); url.pathname = '/sdapi/v1/txt2img'; @@ -781,7 +781,7 @@ drawthings.post('/generate', jsonParser, async (request, response) => { const data = await result.json(); return response.send(data); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -794,21 +794,21 @@ pollinations.post('/models', jsonParser, async (_request, response) => { const result = await fetch(modelsUrl); if (!result.ok) { - console.log('Pollinations returned an error.', result.status, result.statusText); + console.error('Pollinations returned an error.', result.status, result.statusText); throw new Error('Pollinations request failed.'); } const data = await result.json(); if (!Array.isArray(data)) { - console.log('Pollinations returned invalid data.'); + console.error('Pollinations returned invalid data.'); throw new Error('Pollinations request failed.'); } const models = data.map(x => ({ value: x, text: x })); return response.send(models); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -829,12 +829,12 @@ pollinations.post('/generate', jsonParser, async (request, response) => { }); promptUrl.search = params.toString(); - console.log('Pollinations request URL:', promptUrl.toString()); + console.info('Pollinations request URL:', promptUrl.toString()); const result = await fetch(promptUrl); if (!result.ok) { - console.log('Pollinations returned an error.', result.status, result.statusText); + console.error('Pollinations returned an error.', result.status, result.statusText); throw new Error('Pollinations request failed.'); } @@ -843,7 +843,7 @@ pollinations.post('/generate', jsonParser, async (request, response) => { return response.send({ image: base64 }); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -855,13 +855,13 @@ stability.post('/generate', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.STABILITY); if (!key) { - console.log('Stability AI key not found.'); + console.error('Stability AI key not found.'); return response.sendStatus(400); } const { payload, model } = request.body; - console.log('Stability AI request:', model, payload); + console.debug('Stability AI request:', model, payload); const formData = new FormData(); for (const [key, value] of Object.entries(payload)) { @@ -896,14 +896,14 @@ stability.post('/generate', jsonParser, async (request, response) => { if (!result.ok) { const text = await result.text(); - console.log('Stability AI returned an error.', result.status, result.statusText, text); + console.error('Stability AI returned an error.', result.status, result.statusText, text); return response.sendStatus(500); } const buffer = await result.arrayBuffer(); return response.send(Buffer.from(buffer).toString('base64')); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -915,7 +915,7 @@ blockentropy.post('/models', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); if (!key) { - console.log('Block Entropy key not found.'); + console.error('Block Entropy key not found.'); return response.sendStatus(400); } @@ -927,21 +927,21 @@ blockentropy.post('/models', jsonParser, async (request, response) => { }); if (!modelsResponse.ok) { - console.log('Block Entropy returned an error.'); + console.error('Block Entropy returned an error.'); return response.sendStatus(500); } const data = await modelsResponse.json(); if (!Array.isArray(data)) { - console.log('Block Entropy returned invalid data.'); + console.error('Block Entropy returned invalid data.'); return response.sendStatus(500); } const models = data.map(x => ({ value: x.name, text: x.name })); return response.send(models); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -951,11 +951,11 @@ blockentropy.post('/generate', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); if (!key) { - console.log('Block Entropy key not found.'); + console.error('Block Entropy key not found.'); return response.sendStatus(400); } - console.log('Block Entropy request:', request.body); + console.debug('Block Entropy request:', request.body); const result = await fetch('https://api.blockentropy.ai/sdapi/v1/txt2img', { method: 'POST', @@ -976,16 +976,16 @@ blockentropy.post('/generate', jsonParser, async (request, response) => { }); if (!result.ok) { - console.log('Block Entropy returned an error.'); + console.error('Block Entropy returned an error.'); return response.sendStatus(500); } const data = await result.json(); - console.log('Block Entropy response:', data); + console.debug('Block Entropy response:', data); return response.send(data); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -998,11 +998,11 @@ huggingface.post('/generate', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.HUGGINGFACE); if (!key) { - console.log('Hugging Face key not found.'); + console.error('Hugging Face key not found.'); return response.sendStatus(400); } - console.log('Hugging Face request:', request.body); + console.debug('Hugging Face request:', request.body); const result = await fetch(`https://api-inference.huggingface.co/models/${request.body.model}`, { method: 'POST', @@ -1016,7 +1016,7 @@ huggingface.post('/generate', jsonParser, async (request, response) => { }); if (!result.ok) { - console.log('Hugging Face returned an error.'); + console.error('Hugging Face returned an error.'); return response.sendStatus(500); } @@ -1025,7 +1025,7 @@ huggingface.post('/generate', jsonParser, async (request, response) => { image: Buffer.from(buffer).toString('base64'), }); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -1037,7 +1037,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.NANOGPT); if (!key) { - console.log('NanoGPT key not found.'); + console.error('NanoGPT key not found.'); return response.sendStatus(400); } @@ -1050,7 +1050,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => { }); if (!modelsResponse.ok) { - console.log('NanoGPT returned an error.'); + console.error('NanoGPT returned an error.'); return response.sendStatus(500); } @@ -1059,7 +1059,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => { const imageModels = data?.models?.image; if (!imageModels || typeof imageModels !== 'object') { - console.log('NanoGPT returned invalid data.'); + console.error('NanoGPT returned invalid data.'); return response.sendStatus(500); } @@ -1067,7 +1067,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => { return response.send(models); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -1077,11 +1077,11 @@ nanogpt.post('/generate', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.NANOGPT); if (!key) { - console.log('NanoGPT key not found.'); + console.error('NanoGPT key not found.'); return response.sendStatus(400); } - console.log('NanoGPT request:', request.body); + console.debug('NanoGPT request:', request.body); const result = await fetch('https://nano-gpt.com/api/generate-image', { method: 'POST', @@ -1093,7 +1093,7 @@ nanogpt.post('/generate', jsonParser, async (request, response) => { }); if (!result.ok) { - console.log('NanoGPT returned an error.'); + console.error('NanoGPT returned an error.'); return response.sendStatus(500); } @@ -1102,14 +1102,14 @@ nanogpt.post('/generate', jsonParser, async (request, response) => { const image = data?.data?.[0]?.b64_json; if (!image) { - console.log('NanoGPT returned invalid data.'); + console.error('NanoGPT returned invalid data.'); return response.sendStatus(500); } return response.send({ image }); } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); @@ -1121,7 +1121,7 @@ bfl.post('/generate', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.BFL); if (!key) { - console.log('BFL key not found.'); + console.error('BFL key not found.'); return response.sendStatus(400); } @@ -1173,7 +1173,7 @@ bfl.post('/generate', jsonParser, async (request, response) => { delete requestBody.guidance; } - console.log('BFL request:', requestBody); + console.debug('BFL request:', requestBody); const result = await fetch(`https://api.bfl.ml/v1/${request.body.model}`, { method: 'POST', @@ -1185,7 +1185,7 @@ bfl.post('/generate', jsonParser, async (request, response) => { }); if (!result.ok) { - console.log('BFL returned an error.'); + console.error('BFL returned an error.'); return response.sendStatus(500); } @@ -1201,7 +1201,7 @@ bfl.post('/generate', jsonParser, async (request, response) => { if (!statusResult.ok) { const text = await statusResult.text(); - console.log('BFL returned an error.', text); + console.error('BFL returned an error.', text); return response.sendStatus(500); } @@ -1223,7 +1223,7 @@ bfl.post('/generate', jsonParser, async (request, response) => { throw new Error('BFL failed to generate image.', { cause: statusData }); } } catch (error) { - console.log(error); + console.error(error); return response.sendStatus(500); } }); diff --git a/src/endpoints/stats.js b/src/endpoints/stats.js index dbde6cb17..a2077df78 100644 --- a/src/endpoints/stats.js +++ b/src/endpoints/stats.js @@ -148,7 +148,7 @@ async function collectAndCreateStats(chatsPath, charactersPath) { * @param {string} charactersPath Path to the directory containing the character files. */ export async function recreateStats(handle, chatsPath, charactersPath) { - console.log('Collecting and creating stats for user:', handle); + console.info('Collecting and creating stats for user:', handle); const stats = await collectAndCreateStats(chatsPath, charactersPath); STATS.set(handle, stats); await saveStatsToFile(); @@ -200,7 +200,7 @@ async function saveStatsToFile() { await writeFileAtomic(statsFilePath, JSON.stringify(charStats)); TIMESTAMPS.set(handle, Date.now()); } catch (error) { - console.log('Failed to save stats to file.', error); + console.error('Failed to save stats to file.', error); } } } diff --git a/src/endpoints/thumbnails.js b/src/endpoints/thumbnails.js index 8811a5cee..bba6a2a13 100644 --- a/src/endpoints/thumbnails.js +++ b/src/endpoints/thumbnails.js @@ -89,7 +89,6 @@ async function generateThumbnail(directories, type, file) { let thumbnailFolder = getThumbnailFolder(directories, type); let originalFolder = getOriginalFolder(directories, type); if (thumbnailFolder === undefined || originalFolder === undefined) throw new Error('Invalid thumbnail type'); - const pathToCachedFile = path.join(thumbnailFolder, file); const pathToOriginalFile = path.join(originalFolder, file); @@ -104,7 +103,7 @@ async function generateThumbnail(directories, type, file) { const cachedStat = fs.statSync(pathToCachedFile); if (originalStat.mtimeMs > cachedStat.ctimeMs) { - //console.log('Original file changed. Regenerating thumbnail...'); + //console.warn('Original file changed. Regenerating thumbnail...'); shouldRegenerate = true; } } @@ -157,7 +156,7 @@ export async function ensureThumbnailCache() { return; } - console.log('Generating thumbnails cache. Please wait...'); + console.info('Generating thumbnails cache. Please wait...'); const bgFiles = fs.readdirSync(directories.backgrounds); const tasks = []; @@ -167,7 +166,7 @@ export async function ensureThumbnailCache() { } await Promise.all(tasks); - console.log(`Done! Generated: ${bgFiles.length} preview images`); + console.info(`Done! Generated: ${bgFiles.length} preview images`); } } diff --git a/src/endpoints/tokenizers.js b/src/endpoints/tokenizers.js index bd6fdeec0..0f68f79c2 100644 --- a/src/endpoints/tokenizers.js +++ b/src/endpoints/tokenizers.js @@ -96,7 +96,7 @@ async function getPathToTokenizer(model, fallbackModel) { throw new Error('Downloading tokenizers is disabled, the model is not cached'); } - console.log('Downloading tokenizer model:', model); + console.info('Downloading tokenizer model:', model); const response = await fetch(model); if (!response.ok) { throw new Error(`Failed to fetch the model: ${response.status} ${response.statusText}`); @@ -108,7 +108,7 @@ async function getPathToTokenizer(model, fallbackModel) { } catch (error) { const getLastSegment = str => str?.split('/')?.pop() || ''; if (fallbackModel) { - console.log(`Could not get a tokenizer from ${getLastSegment(model)}. Reason: ${error.message}. Using a fallback model: ${getLastSegment(fallbackModel)}.`); + console.error(`Could not get a tokenizer from ${getLastSegment(model)}. Reason: ${error.message}. Using a fallback model: ${getLastSegment(fallbackModel)}.`); return fallbackModel; } @@ -156,7 +156,7 @@ class SentencePieceTokenizer { const pathToModel = await getPathToTokenizer(this.#model, this.#fallbackModel); this.#instance = new SentencePieceProcessor(); await this.#instance.load(pathToModel); - console.log('Instantiated the tokenizer for', path.parse(pathToModel).name); + console.info('Instantiated the tokenizer for', path.parse(pathToModel).name); return this.#instance; } catch (error) { console.error('Sentencepiece tokenizer failed to load: ' + this.#model, error); @@ -205,7 +205,7 @@ class WebTokenizer { const pathToModel = await getPathToTokenizer(this.#model, this.#fallbackModel); const arrayBuffer = fs.readFileSync(pathToModel).buffer; this.#instance = await Tokenizer.fromJSON(arrayBuffer); - console.log('Instantiated the tokenizer for', path.parse(pathToModel).name); + console.info('Instantiated the tokenizer for', path.parse(pathToModel).name); return this.#instance; } catch (error) { console.error('Web tokenizer failed to load: ' + this.#model, error); @@ -442,7 +442,7 @@ export function getTiktokenTokenizer(model) { } const tokenizer = tiktoken.encoding_for_model(model); - console.log('Instantiated the tokenizer for', model); + console.info('Instantiated the tokenizer for', model); tokenizersCache[model] = tokenizer; return tokenizer; } @@ -489,7 +489,7 @@ function createSentencepieceEncodingHandler(tokenizer) { const chunks = instance?.encodePieces(text); return response.send({ ids, count, chunks }); } catch (error) { - console.log(error); + console.error(error); return response.send({ ids: [], count: 0, chunks: [] }); } }; @@ -520,7 +520,7 @@ function createSentencepieceDecodingHandler(tokenizer) { const text = chunks.join(''); return response.send({ text, chunks }); } catch (error) { - console.log(error); + console.error(error); return response.send({ text: '', chunks: [] }); } }; @@ -549,7 +549,7 @@ function createTiktokenEncodingHandler(modelId) { const chunks = await getTiktokenChunks(tokenizer, tokens); return response.send({ ids: tokens, count: tokens.length, chunks }); } catch (error) { - console.log(error); + console.error(error); return response.send({ ids: [], count: 0, chunks: [] }); } }; @@ -578,7 +578,7 @@ function createTiktokenDecodingHandler(modelId) { const text = new TextDecoder().decode(textBytes); return response.send({ text }); } catch (error) { - console.log(error); + console.error(error); return response.send({ text: '' }); } }; @@ -608,7 +608,7 @@ function createWebTokenizerEncodingHandler(tokenizer) { const chunks = getWebTokenizersChunks(instance, tokens); return response.send({ ids: tokens, count: tokens.length, chunks }); } catch (error) { - console.log(error); + console.error(error); return response.send({ ids: [], count: 0, chunks: [] }); } }; @@ -639,7 +639,7 @@ function createWebTokenizerDecodingHandler(tokenizer) { const text = instance.decode(new Int32Array(ids)); return response.send({ text, chunks }); } catch (error) { - console.log(error); + console.error(error); return response.send({ text: '', chunks: [] }); } }; @@ -739,7 +739,7 @@ router.post('/openai/encode', jsonParser, async function (req, res) { const handler = createTiktokenEncodingHandler(model); return handler(req, res); } catch (error) { - console.log(error); + console.error(error); return res.send({ ids: [], count: 0, chunks: [] }); } }); @@ -807,7 +807,7 @@ router.post('/openai/decode', jsonParser, async function (req, res) { const handler = createTiktokenDecodingHandler(model); return handler(req, res); } catch (error) { - console.log(error); + console.error(error); return res.send({ text: '' }); } }); @@ -946,7 +946,7 @@ router.post('/remote/kobold/count', jsonParser, async function (request, respons const result = await fetch(url, args); if (!result.ok) { - console.log(`API returned error: ${result.status} ${result.statusText}`); + console.error(`API returned error: ${result.status} ${result.statusText}`); return response.send({ error: true }); } @@ -955,7 +955,7 @@ router.post('/remote/kobold/count', jsonParser, async function (request, respons const ids = data['ids'] ?? []; return response.send({ count, ids }); } catch (error) { - console.log(error); + console.error(error); return response.send({ error: true }); } }); @@ -1010,7 +1010,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re const result = await fetch(url, args); if (!result.ok) { - console.log(`API returned error: ${result.status} ${result.statusText}`); + console.error(`API returned error: ${result.status} ${result.statusText}`); return response.send({ error: true }); } @@ -1020,7 +1020,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re return response.send({ count, ids }); } catch (error) { - console.log(error); + console.error(error); return response.send({ error: true }); } }); diff --git a/src/endpoints/translate.js b/src/endpoints/translate.js index b8793dced..bcfb36eb1 100644 --- a/src/endpoints/translate.js +++ b/src/endpoints/translate.js @@ -35,7 +35,7 @@ function decodeBuffer(buffer) { try { return iconv.decode(Buffer.from(buffer), 'utf-8'); } catch (error) { - console.log('Failed to decode buffer:', error); + console.warn('Failed to decode buffer:', error); return Buffer.from(buffer).toString('utf-8'); } } @@ -46,7 +46,7 @@ router.post('/libre', jsonParser, async (request, response) => { const url = readSecret(request.user.directories, SECRET_KEYS.LIBRE_URL); if (!url) { - console.log('LibreTranslate URL is not configured.'); + console.error('LibreTranslate URL is not configured.'); return response.sendStatus(400); } @@ -69,7 +69,7 @@ router.post('/libre', jsonParser, async (request, response) => { return response.sendStatus(400); } - console.log('Input text: ' + text); + console.debug('Input text: ' + text); const result = await fetch(url, { method: 'POST', @@ -85,17 +85,17 @@ router.post('/libre', jsonParser, async (request, response) => { if (!result.ok) { const error = await result.text(); - console.log('LibreTranslate error: ', result.statusText, error); + console.error('LibreTranslate error: ', result.statusText, error); return response.sendStatus(500); } /** @type {any} */ const json = await result.json(); - console.log('Translated text: ' + json.translatedText); + console.debug('Translated text: ' + json.translatedText); return response.send(json.translatedText); } catch (error) { - console.log('Translation error: ' + error.message); + console.error('Translation error: ' + error.message); return response.sendStatus(500); } }); @@ -109,14 +109,14 @@ router.post('/google', jsonParser, async (request, response) => { return response.sendStatus(400); } - console.log('Input text: ' + text); + console.debug('Input text: ' + text); const { generateRequestUrl, normaliseResponse } = getGoogleTranslateClient(); const requestUrl = generateRequestUrl(text, { to: lang }); const result = await fetch(requestUrl); if (!result.ok) { - console.log('Google Translate error: ', result.statusText); + console.error('Google Translate error: ', result.statusText); return response.sendStatus(500); } @@ -125,10 +125,10 @@ router.post('/google', jsonParser, async (request, response) => { const translatedText = translateResponse.text; response.setHeader('Content-Type', 'text/plain; charset=utf-8'); - console.log('Translated text: ' + translatedText); + console.debug('Translated text: ' + translatedText); return response.send(translatedText); } catch (error) { - console.log('Translation error', error); + console.error('Translation error', error); return response.sendStatus(500); } }); @@ -161,7 +161,7 @@ router.post('/yandex', jsonParser, async (request, response) => { params.append('lang', lang); const ucid = uuidv4().replaceAll('-', ''); - console.log('Input text: ' + inputText); + console.debug('Input text: ' + inputText); const result = await fetch(`https://translate.yandex.net/api/v1/tr.json/translate?ucid=${ucid}&srv=android&format=text`, { method: 'POST', @@ -173,18 +173,18 @@ router.post('/yandex', jsonParser, async (request, response) => { if (!result.ok) { const error = await result.text(); - console.log('Yandex error: ', result.statusText, error); + console.error('Yandex error: ', result.statusText, error); return response.sendStatus(500); } /** @type {any} */ const json = await result.json(); const translated = json.text.join(); - console.log('Translated text: ' + translated); + console.debug('Translated text: ' + translated); return response.send(translated); } catch (error) { - console.log('Translation error: ' + error.message); + console.error('Translation error: ' + error.message); return response.sendStatus(500); } }); @@ -195,7 +195,7 @@ router.post('/lingva', jsonParser, async (request, response) => { const baseUrl = secretUrl || LINGVA_DEFAULT; if (!secretUrl && baseUrl === LINGVA_DEFAULT) { - console.log('Lingva URL is using default value.', LINGVA_DEFAULT); + console.warn('Lingva URL is using default value.', LINGVA_DEFAULT); } if (request.body.lang === 'zh-CN' || request.body.lang === 'zh-TW') { @@ -213,22 +213,22 @@ router.post('/lingva', jsonParser, async (request, response) => { return response.sendStatus(400); } - console.log('Input text: ' + text); + console.debug('Input text: ' + text); const url = urlJoin(baseUrl, 'auto', lang, encodeURIComponent(text)); const result = await fetch(url); if (!result.ok) { const error = await result.text(); - console.log('Lingva error: ', result.statusText, error); + console.error('Lingva error: ', result.statusText, error); } /** @type {any} */ const data = await result.json(); - console.log('Translated text: ' + data.translation); + console.debug('Translated text: ' + data.translation); return response.send(data.translation); } catch (error) { - console.log('Translation error', error); + console.error('Translation error', error); return response.sendStatus(500); } }); @@ -238,7 +238,7 @@ router.post('/deepl', jsonParser, async (request, response) => { const key = readSecret(request.user.directories, SECRET_KEYS.DEEPL); if (!key) { - console.log('DeepL key is not configured.'); + console.error('DeepL key is not configured.'); return response.sendStatus(400); } @@ -254,7 +254,7 @@ router.post('/deepl', jsonParser, async (request, response) => { return response.sendStatus(400); } - console.log('Input text: ' + text); + console.debug('Input text: ' + text); const params = new URLSearchParams(); params.append('text', text); @@ -280,17 +280,17 @@ router.post('/deepl', jsonParser, async (request, response) => { if (!result.ok) { const error = await result.text(); - console.log('DeepL error: ', result.statusText, error); + console.error('DeepL error: ', result.statusText, error); return response.sendStatus(500); } /** @type {any} */ const json = await result.json(); - console.log('Translated text: ' + json.translations[0].text); + console.debug('Translated text: ' + json.translations[0].text); return response.send(json.translations[0].text); } catch (error) { - console.log('Translation error: ' + error.message); + console.error('Translation error: ' + error.message); return response.sendStatus(500); } }); @@ -376,7 +376,7 @@ router.post('/deeplx', jsonParser, async (request, response) => { return response.sendStatus(400); } - console.log('Input text: ' + text); + console.debug('Input text: ' + text); const result = await fetch(url, { method: 'POST', @@ -393,17 +393,17 @@ router.post('/deeplx', jsonParser, async (request, response) => { if (!result.ok) { const error = await result.text(); - console.log('DeepLX error: ', result.statusText, error); + console.error('DeepLX error: ', result.statusText, error); return response.sendStatus(500); } /** @type {any} */ const json = await result.json(); - console.log('Translated text: ' + json.data); + console.debug('Translated text: ' + json.data); return response.send(json.data); } catch (error) { - console.log('DeepLX translation error: ' + error.message); + console.error('DeepLX translation error: ' + error.message); return response.sendStatus(500); } }); @@ -429,14 +429,14 @@ router.post('/bing', jsonParser, async (request, response) => { return response.sendStatus(400); } - console.log('Input text: ' + text); + console.debug('Input text: ' + text); const result = await bingTranslate(text, null, lang); const translatedText = result?.translation; - console.log('Translated text: ' + translatedText); + console.debug('Translated text: ' + translatedText); return response.send(translatedText); } catch (error) { - console.log('Translation error', error); + console.error('Translation error', error); return response.sendStatus(500); } }); diff --git a/src/endpoints/users-admin.js b/src/endpoints/users-admin.js index 6b3e251aa..2e7ea9318 100644 --- a/src/endpoints/users-admin.js +++ b/src/endpoints/users-admin.js @@ -53,12 +53,12 @@ router.post('/get', requireAdminMiddleware, jsonParser, async (_request, respons router.post('/disable', requireAdminMiddleware, jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Disable user failed: Missing required fields'); + console.error('Disable user failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (request.body.handle === request.user.profile.handle) { - console.log('Disable user failed: Cannot disable yourself'); + console.error('Disable user failed: Cannot disable yourself'); return response.status(400).json({ error: 'Cannot disable yourself' }); } @@ -66,7 +66,7 @@ router.post('/disable', requireAdminMiddleware, jsonParser, async (request, resp const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Disable user failed: User not found'); + console.error('Disable user failed: User not found'); return response.status(404).json({ error: 'User not found' }); } @@ -82,7 +82,7 @@ router.post('/disable', requireAdminMiddleware, jsonParser, async (request, resp router.post('/enable', requireAdminMiddleware, jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Enable user failed: Missing required fields'); + console.error('Enable user failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } @@ -90,7 +90,7 @@ router.post('/enable', requireAdminMiddleware, jsonParser, async (request, respo const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Enable user failed: User not found'); + console.error('Enable user failed: User not found'); return response.status(404).json({ error: 'User not found' }); } @@ -106,7 +106,7 @@ router.post('/enable', requireAdminMiddleware, jsonParser, async (request, respo router.post('/promote', requireAdminMiddleware, jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Promote user failed: Missing required fields'); + console.error('Promote user failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } @@ -114,7 +114,7 @@ router.post('/promote', requireAdminMiddleware, jsonParser, async (request, resp const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Promote user failed: User not found'); + console.error('Promote user failed: User not found'); return response.status(404).json({ error: 'User not found' }); } @@ -130,12 +130,12 @@ router.post('/promote', requireAdminMiddleware, jsonParser, async (request, resp router.post('/demote', requireAdminMiddleware, jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Demote user failed: Missing required fields'); + console.error('Demote user failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (request.body.handle === request.user.profile.handle) { - console.log('Demote user failed: Cannot demote yourself'); + console.error('Demote user failed: Cannot demote yourself'); return response.status(400).json({ error: 'Cannot demote yourself' }); } @@ -143,7 +143,7 @@ router.post('/demote', requireAdminMiddleware, jsonParser, async (request, respo const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Demote user failed: User not found'); + console.error('Demote user failed: User not found'); return response.status(404).json({ error: 'User not found' }); } @@ -159,7 +159,7 @@ router.post('/demote', requireAdminMiddleware, jsonParser, async (request, respo router.post('/create', requireAdminMiddleware, jsonParser, async (request, response) => { try { if (!request.body.handle || !request.body.name) { - console.log('Create user failed: Missing required fields'); + console.error('Create user failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } @@ -167,12 +167,12 @@ router.post('/create', requireAdminMiddleware, jsonParser, async (request, respo const handle = lodash.kebabCase(String(request.body.handle).toLowerCase().trim()); if (!handle) { - console.log('Create user failed: Invalid handle'); + console.error('Create user failed: Invalid handle'); return response.status(400).json({ error: 'Invalid handle' }); } if (handles.some(x => x === handle)) { - console.log('Create user failed: User with that handle already exists'); + console.error('Create user failed: User with that handle already exists'); return response.status(409).json({ error: 'User already exists' }); } @@ -192,7 +192,7 @@ router.post('/create', requireAdminMiddleware, jsonParser, async (request, respo await storage.setItem(toKey(handle), newUser); // Create user directories - console.log('Creating data directories for', newUser.handle); + console.info('Creating data directories for', newUser.handle); await ensurePublicDirectoriesExist(); const directories = getUserDirectories(newUser.handle); await checkForNewContent([directories]); @@ -206,17 +206,17 @@ router.post('/create', requireAdminMiddleware, jsonParser, async (request, respo router.post('/delete', requireAdminMiddleware, jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Delete user failed: Missing required fields'); + console.error('Delete user failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (request.body.handle === request.user.profile.handle) { - console.log('Delete user failed: Cannot delete yourself'); + console.error('Delete user failed: Cannot delete yourself'); return response.status(400).json({ error: 'Cannot delete yourself' }); } if (request.body.handle === DEFAULT_USER.handle) { - console.log('Delete user failed: Cannot delete default user'); + console.error('Delete user failed: Cannot delete default user'); return response.status(400).json({ error: 'Sorry, but the default user cannot be deleted. It is required as a fallback.' }); } @@ -224,7 +224,7 @@ router.post('/delete', requireAdminMiddleware, jsonParser, async (request, respo if (request.body.purge) { const directories = getUserDirectories(request.body.handle); - console.log('Deleting data directories for', request.body.handle); + console.info('Deleting data directories for', request.body.handle); await fsPromises.rm(directories.root, { recursive: true, force: true }); } @@ -238,7 +238,7 @@ router.post('/delete', requireAdminMiddleware, jsonParser, async (request, respo router.post('/slugify', requireAdminMiddleware, jsonParser, async (request, response) => { try { if (!request.body.text) { - console.log('Slugify failed: Missing required fields'); + console.error('Slugify failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } diff --git a/src/endpoints/users-private.js b/src/endpoints/users-private.js index 81b60acea..65b3ca6c6 100644 --- a/src/endpoints/users-private.js +++ b/src/endpoints/users-private.js @@ -57,18 +57,18 @@ router.get('/me', async (request, response) => { router.post('/change-avatar', jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Change avatar failed: Missing required fields'); + console.error('Change avatar failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (request.body.handle !== request.user.profile.handle && !request.user.profile.admin) { - console.log('Change avatar failed: Unauthorized'); + console.error('Change avatar failed: Unauthorized'); return response.status(403).json({ error: 'Unauthorized' }); } // Avatar is not a data URL or not an empty string if (!request.body.avatar.startsWith('data:image/') && request.body.avatar !== '') { - console.log('Change avatar failed: Invalid data URL'); + console.error('Change avatar failed: Invalid data URL'); return response.status(400).json({ error: 'Invalid data URL' }); } @@ -76,7 +76,7 @@ router.post('/change-avatar', jsonParser, async (request, response) => { const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Change avatar failed: User not found'); + console.error('Change avatar failed: User not found'); return response.status(404).json({ error: 'User not found' }); } @@ -92,12 +92,12 @@ router.post('/change-avatar', jsonParser, async (request, response) => { router.post('/change-password', jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Change password failed: Missing required fields'); + console.error('Change password failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (request.body.handle !== request.user.profile.handle && !request.user.profile.admin) { - console.log('Change password failed: Unauthorized'); + console.error('Change password failed: Unauthorized'); return response.status(403).json({ error: 'Unauthorized' }); } @@ -105,17 +105,17 @@ router.post('/change-password', jsonParser, async (request, response) => { const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Change password failed: User not found'); + console.error('Change password failed: User not found'); return response.status(404).json({ error: 'User not found' }); } if (!user.enabled) { - console.log('Change password failed: User is disabled'); + console.error('Change password failed: User is disabled'); return response.status(403).json({ error: 'User is disabled' }); } if (!request.user.profile.admin && user.password && user.password !== getPasswordHash(request.body.oldPassword, user.salt)) { - console.log('Change password failed: Incorrect password'); + console.error('Change password failed: Incorrect password'); return response.status(403).json({ error: 'Incorrect password' }); } @@ -141,12 +141,12 @@ router.post('/backup', jsonParser, async (request, response) => { const handle = request.body.handle; if (!handle) { - console.log('Backup failed: Missing required fields'); + console.error('Backup failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (handle !== request.user.profile.handle && !request.user.profile.admin) { - console.log('Backup failed: Unauthorized'); + console.error('Backup failed: Unauthorized'); return response.status(403).json({ error: 'Unauthorized' }); } @@ -162,7 +162,7 @@ router.post('/reset-settings', jsonParser, async (request, response) => { const password = request.body.password; if (request.user.profile.password && request.user.profile.password !== getPasswordHash(password, request.user.profile.salt)) { - console.log('Reset settings failed: Incorrect password'); + console.error('Reset settings failed: Incorrect password'); return response.status(403).json({ error: 'Incorrect password' }); } @@ -180,12 +180,12 @@ router.post('/reset-settings', jsonParser, async (request, response) => { router.post('/change-name', jsonParser, async (request, response) => { try { if (!request.body.name || !request.body.handle) { - console.log('Change name failed: Missing required fields'); + console.error('Change name failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (request.body.handle !== request.user.profile.handle && !request.user.profile.admin) { - console.log('Change name failed: Unauthorized'); + console.error('Change name failed: Unauthorized'); return response.status(403).json({ error: 'Unauthorized' }); } @@ -193,7 +193,7 @@ router.post('/change-name', jsonParser, async (request, response) => { const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Change name failed: User not found'); + console.error('Change name failed: User not found'); return response.status(404).json({ error: 'User not found' }); } @@ -210,9 +210,9 @@ router.post('/change-name', jsonParser, async (request, response) => { router.post('/reset-step1', jsonParser, async (request, response) => { try { const resetCode = String(crypto.randomInt(1000, 9999)); - console.log(); - console.log(color.magenta(`${request.user.profile.name}, your account reset code is: `) + color.red(resetCode)); - console.log(); + console.info(); + console.info(color.magenta(`${request.user.profile.name}, your account reset code is: `) + color.red(resetCode)); + console.info(); RESET_CACHE.set(request.user.profile.handle, resetCode); return response.sendStatus(204); } catch (error) { @@ -224,23 +224,23 @@ router.post('/reset-step1', jsonParser, async (request, response) => { router.post('/reset-step2', jsonParser, async (request, response) => { try { if (!request.body.code) { - console.log('Recover step 2 failed: Missing required fields'); + console.error('Recover step 2 failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } if (request.user.profile.password && request.user.profile.password !== getPasswordHash(request.body.password, request.user.profile.salt)) { - console.log('Recover step 2 failed: Incorrect password'); + console.error('Recover step 2 failed: Incorrect password'); return response.status(400).json({ error: 'Incorrect password' }); } const code = RESET_CACHE.get(request.user.profile.handle); if (!code || code !== request.body.code) { - console.log('Recover step 2 failed: Incorrect code'); + console.error('Recover step 2 failed: Incorrect code'); return response.status(400).json({ error: 'Incorrect code' }); } - console.log('Resetting account data:', request.user.profile.handle); + console.info('Resetting account data:', request.user.profile.handle); await fsPromises.rm(request.user.directories.root, { recursive: true, force: true }); await ensurePublicDirectoriesExist(); diff --git a/src/endpoints/users-public.js b/src/endpoints/users-public.js index 4603be488..217cef3d6 100644 --- a/src/endpoints/users-public.js +++ b/src/endpoints/users-public.js @@ -56,7 +56,7 @@ router.post('/list', async (_request, response) => { router.post('/login', jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Login failed: Missing required fields'); + console.error('Login failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } @@ -67,17 +67,17 @@ router.post('/login', jsonParser, async (request, response) => { const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Login failed: User', request.body.handle, 'not found'); + console.error('Login failed: User', request.body.handle, 'not found'); return response.status(403).json({ error: 'Incorrect credentials' }); } if (!user.enabled) { - console.log('Login failed: User', user.handle, 'is disabled'); + console.error('Login failed: User', user.handle, 'is disabled'); return response.status(403).json({ error: 'User is disabled' }); } if (user.password && user.password !== getPasswordHash(request.body.password, user.salt)) { - console.log('Login failed: Incorrect password for', user.handle); + console.error('Login failed: Incorrect password for', user.handle); return response.status(403).json({ error: 'Incorrect credentials' }); } @@ -88,11 +88,11 @@ router.post('/login', jsonParser, async (request, response) => { await loginLimiter.delete(ip); request.session.handle = user.handle; - console.log('Login successful:', user.handle, 'from', ip, 'at', new Date().toLocaleString()); + console.info('Login successful:', user.handle, 'from', ip, 'at', new Date().toLocaleString()); return response.json({ handle: user.handle }); } catch (error) { if (error instanceof RateLimiterRes) { - console.log('Login failed: Rate limited from', getIpFromRequest(request)); + console.error('Login failed: Rate limited from', getIpFromRequest(request)); return response.status(429).send({ error: 'Too many attempts. Try again later or recover your password.' }); } @@ -104,7 +104,7 @@ router.post('/login', jsonParser, async (request, response) => { router.post('/recover-step1', jsonParser, async (request, response) => { try { if (!request.body.handle) { - console.log('Recover step 1 failed: Missing required fields'); + console.error('Recover step 1 failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } @@ -115,24 +115,24 @@ router.post('/recover-step1', jsonParser, async (request, response) => { const user = await storage.getItem(toKey(request.body.handle)); if (!user) { - console.log('Recover step 1 failed: User', request.body.handle, 'not found'); + console.error('Recover step 1 failed: User', request.body.handle, 'not found'); return response.status(404).json({ error: 'User not found' }); } if (!user.enabled) { - console.log('Recover step 1 failed: User', user.handle, 'is disabled'); + console.error('Recover step 1 failed: User', user.handle, 'is disabled'); return response.status(403).json({ error: 'User is disabled' }); } const mfaCode = String(crypto.randomInt(1000, 9999)); - console.log(); - console.log(color.blue(`${user.name}, your password recovery code is: `) + color.magenta(mfaCode)); - console.log(); + console.info(); + console.info(color.blue(`${user.name}, your password recovery code is: `) + color.magenta(mfaCode)); + console.info(); MFA_CACHE.set(user.handle, mfaCode); return response.sendStatus(204); } catch (error) { if (error instanceof RateLimiterRes) { - console.log('Recover step 1 failed: Rate limited from', getIpFromRequest(request)); + console.error('Recover step 1 failed: Rate limited from', getIpFromRequest(request)); return response.status(429).send({ error: 'Too many attempts. Try again later or contact your admin.' }); } @@ -144,7 +144,7 @@ router.post('/recover-step1', jsonParser, async (request, response) => { router.post('/recover-step2', jsonParser, async (request, response) => { try { if (!request.body.handle || !request.body.code) { - console.log('Recover step 2 failed: Missing required fields'); + console.error('Recover step 2 failed: Missing required fields'); return response.status(400).json({ error: 'Missing required fields' }); } @@ -153,12 +153,12 @@ router.post('/recover-step2', jsonParser, async (request, response) => { const ip = getIpFromRequest(request); if (!user) { - console.log('Recover step 2 failed: User', request.body.handle, 'not found'); + console.error('Recover step 2 failed: User', request.body.handle, 'not found'); return response.status(404).json({ error: 'User not found' }); } if (!user.enabled) { - console.log('Recover step 2 failed: User', user.handle, 'is disabled'); + console.error('Recover step 2 failed: User', user.handle, 'is disabled'); return response.status(403).json({ error: 'User is disabled' }); } @@ -166,7 +166,7 @@ router.post('/recover-step2', jsonParser, async (request, response) => { if (request.body.code !== mfaCode) { await recoverLimiter.consume(ip); - console.log('Recover step 2 failed: Incorrect code'); + console.error('Recover step 2 failed: Incorrect code'); return response.status(403).json({ error: 'Incorrect code' }); } @@ -186,7 +186,7 @@ router.post('/recover-step2', jsonParser, async (request, response) => { return response.sendStatus(204); } catch (error) { if (error instanceof RateLimiterRes) { - console.log('Recover step 2 failed: Rate limited from', getIpFromRequest(request)); + console.error('Recover step 2 failed: Rate limited from', getIpFromRequest(request)); return response.status(429).send({ error: 'Too many attempts. Try again later or contact your admin.' }); } diff --git a/src/endpoints/vectors.js b/src/endpoints/vectors.js index 325684601..41b5ab7ce 100644 --- a/src/endpoints/vectors.js +++ b/src/endpoints/vectors.js @@ -360,7 +360,7 @@ async function regenerateCorruptedIndexErrorHandler(req, res, error) { if (exists) { const path = index.folderPath; - console.error(`Corrupted index detected at ${path}, regenerating...`); + console.warn(`Corrupted index detected at ${path}, regenerating...`); await index.deleteIndex(); return res.redirect(307, req.originalUrl + '?regenerated=true'); } @@ -474,7 +474,7 @@ router.post('/purge-all', jsonParser, async (req, res) => { continue; } await fs.promises.rm(sourcePath, { recursive: true }); - console.log(`Deleted vector source store at ${sourcePath}`); + console.info(`Deleted vector source store at ${sourcePath}`); } return res.sendStatus(200); @@ -498,7 +498,7 @@ router.post('/purge', jsonParser, async (req, res) => { continue; } await fs.promises.rm(sourcePath, { recursive: true }); - console.log(`Deleted vector index at ${sourcePath}`); + console.info(`Deleted vector index at ${sourcePath}`); } return res.sendStatus(200); diff --git a/src/endpoints/worldinfo.js b/src/endpoints/worldinfo.js index e0b3bd269..aeaa2eb55 100644 --- a/src/endpoints/worldinfo.js +++ b/src/endpoints/worldinfo.js @@ -25,7 +25,7 @@ export function readWorldInfoFile(directories, worldInfoName, allowDummy) { const pathToWorldInfo = path.join(directories.worlds, filename); if (!fs.existsSync(pathToWorldInfo)) { - console.log(`World info file ${filename} doesn't exist.`); + console.error(`World info file ${filename} doesn't exist.`); return dummyObject; } diff --git a/src/request-proxy.js b/src/request-proxy.js index 3ad8a7046..92be93e83 100644 --- a/src/request-proxy.js +++ b/src/request-proxy.js @@ -43,9 +43,9 @@ export default function initRequestProxy({ enabled, url, bypass }) { http.globalAgent = proxyAgent; https.globalAgent = proxyAgent; - console.log(); - console.log(color.green(LOG_HEADER), 'Proxy URL is used:', color.blue(url)); - console.log(); + console.info(); + console.info(color.green(LOG_HEADER), 'Proxy URL is used:', color.blue(url)); + console.info(); } catch (error) { console.error(color.red(LOG_HEADER), 'Failed to initialize request proxy:', error); } diff --git a/src/util.js b/src/util.js index 0fe03e76c..d8df3bfee 100644 --- a/src/util.js +++ b/src/util.js @@ -13,6 +13,7 @@ import _ from 'lodash'; import yauzl from 'yauzl'; import mime from 'mime-types'; import { default as simpleGit } from 'simple-git'; +import { LOG_LEVELS } from './constants.js'; /** * Parsed config object. @@ -149,6 +150,7 @@ export function getHexString(length) { */ export function formatBytes(bytes) { if (bytes === 0) return '0 B'; + const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); @@ -285,10 +287,11 @@ export function deepMerge(target, source) { if (isObject(target) && isObject(source)) { Object.keys(source).forEach(key => { if (isObject(source[key])) { - if (!(key in target)) + if (!(key in target)) { Object.assign(output, { [key]: source[key] }); - else + } else { output[key] = deepMerge(target[key], source[key]); + } } else { Object.assign(output, { [key]: source[key] }); } @@ -466,7 +469,9 @@ export function forwardFetchResponse(from, to) { from.body.pipe(to); to.socket.on('close', function () { - if (from.body instanceof Readable) from.body.destroy(); // Close the remote stream + if (from.body instanceof Readable) { + from.body.destroy(); // Close the remote stream + } to.end(); // End the Express response }); @@ -692,6 +697,19 @@ export function isValidUrl(url) { } } +/** + * Setup the minimum log level + */ +export function setupLogLevel() { + const logLevel = getConfigValue('minLogLevel', LOG_LEVELS.DEBUG); + + globalThis.console.debug = logLevel <= LOG_LEVELS.DEBUG ? console.debug : () => {}; + globalThis.console.log = logLevel <= LOG_LEVELS.INFO ? console.log : () => {}; + globalThis.console.info = logLevel <= LOG_LEVELS.INFO ? console.info : () => {}; + globalThis.console.warn = logLevel <= LOG_LEVELS.WARN ? console.warn : () => {}; + globalThis.console.error = logLevel <= LOG_LEVELS.ERROR ? console.error : () => {}; +} + /** * MemoryLimitedMap class that limits the memory usage of string values. */