Rewritten minLogLevel feature

This commit is contained in:
Eradev
2025-01-15 10:02:32 -05:00
parent 78e67080c9
commit 1f9fa74786
44 changed files with 580 additions and 561 deletions

View File

@ -65,6 +65,8 @@ autheliaAuth: false
# the username and passwords for basic auth are the same as those # the username and passwords for basic auth are the same as those
# for the individual accounts # for the individual accounts
perUserBasicAuth: false 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). # User session timeout *in seconds* (defaults to 24 hours).
## Set to a positive number to expire session after a certain time of inactivity ## Set to a positive number to expire session after a certain time of inactivity

View File

@ -59,6 +59,7 @@ const hash_derivations = {
// Tulu-3-8B // Tulu-3-8B
// Tulu-3-70B // Tulu-3-70B
'Tulu' 'Tulu'
,
}; };
const substr_derivations = { 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; return null;
} }

View File

@ -1,15 +1,13 @@
import { getRequestHeaders, substituteParams } from '../../../../script.js'; import { getRequestHeaders, substituteParams } from '../../../../script.js';
import { Popup, POPUP_RESULT, POPUP_TYPE } from '../../../popup.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 { SlashCommandParser } from '../../../slash-commands/SlashCommandParser.js';
import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js'; import { debounceAsync, warn } from '../index.js';
import { debounceAsync, log, warn } from '../index.js';
import { QuickReply } from './QuickReply.js'; import { QuickReply } from './QuickReply.js';
export class QuickReplySet { export class QuickReplySet {
/**@type {QuickReplySet[]}*/ static list = []; /**@type {QuickReplySet[]}*/ static list = [];
static from(props) { static from(props) {
props.qrList = []; //props.qrList?.map(it=>QuickReply.from(it)); props.qrList = []; //props.qrList?.map(it=>QuickReply.from(it));
const instance = Object.assign(new this(), props); const instance = Object.assign(new this(), props);
@ -24,9 +22,6 @@ export class QuickReplySet {
return this.list.find(it=>it.name == name); return this.list.find(it=>it.name == name);
} }
/**@type {string}*/ name; /**@type {string}*/ name;
/**@type {boolean}*/ disableSend = false; /**@type {boolean}*/ disableSend = false;
/**@type {boolean}*/ placeBeforeInput = false; /**@type {boolean}*/ placeBeforeInput = false;
@ -34,19 +29,12 @@ export class QuickReplySet {
/**@type {string}*/ color = 'transparent'; /**@type {string}*/ color = 'transparent';
/**@type {boolean}*/ onlyBorderColor = false; /**@type {boolean}*/ onlyBorderColor = false;
/**@type {QuickReply[]}*/ qrList = []; /**@type {QuickReply[]}*/ qrList = [];
/**@type {number}*/ idIndex = 0; /**@type {number}*/ idIndex = 0;
/**@type {boolean}*/ isDeleted = false; /**@type {boolean}*/ isDeleted = false;
/**@type {function}*/ save; /**@type {function}*/ save;
/**@type {HTMLElement}*/ dom; /**@type {HTMLElement}*/ dom;
/**@type {HTMLElement}*/ settingsDom; /**@type {HTMLElement}*/ settingsDom;
constructor() { constructor() {
this.save = debounceAsync(()=>this.performSave(), 200); this.save = debounceAsync(()=>this.performSave(), 200);
} }
@ -55,9 +43,6 @@ export class QuickReplySet {
this.qrList.forEach(qr=>this.hookQuickReply(qr)); this.qrList.forEach(qr=>this.hookQuickReply(qr));
} }
unrender() { unrender() {
this.dom?.remove(); this.dom?.remove();
this.dom = null; this.dom = null;
@ -100,9 +85,6 @@ export class QuickReplySet {
} }
} }
renderSettings() { renderSettings() {
if (!this.settingsDom) { if (!this.settingsDom) {
this.settingsDom = document.createElement('div'); { this.settingsDom = document.createElement('div'); {
@ -123,9 +105,6 @@ export class QuickReplySet {
this.settingsDom.append(qr.renderSettings(idx)); this.settingsDom.append(qr.renderSettings(idx));
} }
/** /**
* *
* @param {QuickReply} qr * @param {QuickReply} qr
@ -138,6 +117,7 @@ export class QuickReplySet {
closure.scope.setMacro('arg::*', ''); closure.scope.setMacro('arg::*', '');
return (await closure.execute())?.pipe; return (await closure.execute())?.pipe;
} }
/** /**
* *
* @param {QuickReply} qr The QR to execute. * @param {QuickReply} qr The QR to execute.
@ -207,6 +187,7 @@ export class QuickReplySet {
document.querySelector('#send_but').click(); document.querySelector('#send_but').click();
} }
} }
/** /**
* @param {QuickReply} qr * @param {QuickReply} qr
* @param {string} [message] - optional altered message to be used * @param {string} [message] - optional altered message to be used
@ -220,9 +201,6 @@ export class QuickReplySet {
}); });
} }
addQuickReply(data = {}) { addQuickReply(data = {}) {
const id = Math.max(this.idIndex, this.qrList.reduce((max,qr)=>Math.max(max,qr.id),0)) + 1; const id = Math.max(this.idIndex, this.qrList.reduce((max,qr)=>Math.max(max,qr.id),0)) + 1;
data.id = data.id =
@ -239,6 +217,7 @@ export class QuickReplySet {
this.save(); this.save();
return qr; return qr;
} }
addQuickReplyFromText(qrJson) { addQuickReplyFromText(qrJson) {
let data; let data;
if (qrJson) { if (qrJson) {
@ -371,7 +350,6 @@ export class QuickReplySet {
this.save(); this.save();
} }
toJSON() { toJSON() {
return { return {
version: 2, version: 2,
@ -386,7 +364,6 @@ export class QuickReplySet {
}; };
} }
async performSave() { async performSave() {
const response = await fetch('/api/quick-replies/save', { const response = await fetch('/api/quick-replies/save', {
method: 'POST', method: 'POST',

View File

@ -1638,14 +1638,12 @@ jQuery(async () => {
} }
return textResult; return textResult;
}; };
if (args.return === 'chunks') { if (args.return === 'chunks') {
return getChunksText(); return getChunksText();
} }
// @ts-ignore // @ts-ignore
return slashCommandReturnHelper.doReturn(args.return ?? 'object', urls, { objectToStringFunc: list => list.join('\n') }); return slashCommandReturnHelper.doReturn(args.return ?? 'object', urls, { objectToStringFunc: list => list.join('\n') });
}, },
aliases: ['databank-search', 'data-bank-search'], 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.', 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', defaultValue: 'object',
enumList: [ enumList: [
new SlashCommandEnumValue('chunks', 'Return the actual content chunks', enumTypes.enum, '{}'), new SlashCommandEnumValue('chunks', 'Return the actual content chunks', enumTypes.enum, '{}'),
...slashCommandReturnHelper.enumList({ allowObject: true }) ...slashCommandReturnHelper.enumList({ allowObject: true }),
], ],
forceEnum: true, forceEnum: true,
}) }),
], ],
unnamedArgumentList: [ unnamedArgumentList: [
new SlashCommandArgument('Query to search by.', ARGUMENT_TYPE.STRING, true, false), new SlashCommandArgument('Query to search by.', ARGUMENT_TYPE.STRING, true, false),

View File

@ -67,6 +67,7 @@ import {
forwardFetchResponse, forwardFetchResponse,
removeColorFormatting, removeColorFormatting,
getSeparator, getSeparator,
setupLogLevel,
} from './src/util.js'; } from './src/util.js';
import { UPLOADS_DIRECTORY } from './src/constants.js'; import { UPLOADS_DIRECTORY } from './src/constants.js';
import { ensureThumbnailCache } from './src/endpoints/thumbnails.js'; import { ensureThumbnailCache } from './src/endpoints/thumbnails.js';
@ -688,8 +689,9 @@ const preSetupTasks = async function () {
function getAutorunHostname() { function getAutorunHostname() {
if (autorunHostname === 'auto') { if (autorunHostname === 'auto') {
if (enableIPv6 && enableIPv4) { if (enableIPv6 && enableIPv4) {
if (avoidLocalhost) return '[::1]'; return avoidLocalhost
return 'localhost'; ? '[::1]'
: 'localhost';
} }
if (enableIPv6) { if (enableIPv6) {
@ -755,6 +757,8 @@ const postSetupTasks = async function (v6Failed, v4Failed) {
} }
} }
} }
setupLogLevel();
}; };
/** /**

View File

@ -413,3 +413,10 @@ export const VLLM_KEYS = [
'guided_decoding_backend', 'guided_decoding_backend',
'guided_whitespace_pattern', 'guided_whitespace_pattern',
]; ];
export const LOG_LEVELS = {
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3,
};

View File

@ -32,7 +32,7 @@ router.post('/caption-image', jsonParser, async (request, response) => {
max_tokens: 4096, max_tokens: 4096,
}; };
console.log('Multimodal captioning request', body); console.debug('Multimodal captioning request', body);
const result = await fetch(url, { const result = await fetch(url, {
body: JSON.stringify(body), body: JSON.stringify(body),
@ -46,14 +46,14 @@ router.post('/caption-image', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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 }); return response.status(result.status).send({ error: true });
} }
/** @type {any} */ /** @type {any} */
const generateResponseJson = await result.json(); const generateResponseJson = await result.json();
const caption = generateResponseJson.content[0].text; const caption = generateResponseJson.content[0].text;
console.log('Claude response:', generateResponseJson); console.debug('Claude response:', generateResponseJson);
if (!caption) { if (!caption) {
return response.status(500).send('No caption found'); return response.status(500).send('No caption found');

View File

@ -176,7 +176,7 @@ router.post('/get', jsonParser, async (request, response) => {
} }
} }
catch (err) { catch (err) {
console.log(err); console.error(err);
} }
return response.send(output); return response.send(output);
}); });
@ -200,7 +200,7 @@ router.post('/download', jsonParser, async (request, response) => {
category = i; category = i;
if (category === null) { if (category === null) {
console.debug('Bad request: unsupported asset category.'); console.error('Bad request: unsupported asset category.');
return response.sendStatus(400); 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 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); 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 { try {
// Download to temp // Download to temp
@ -224,7 +224,9 @@ router.post('/download', jsonParser, async (request, response) => {
// Delete if previous download failed // Delete if previous download failed
if (fs.existsSync(temp_path)) { if (fs.existsSync(temp_path)) {
fs.unlink(temp_path, (err) => { fs.unlink(temp_path, (err) => {
if (err) throw err; if (err) {
throw err;
}
}); });
} }
const fileStream = fs.createWriteStream(destination, { flags: 'wx' }); const fileStream = fs.createWriteStream(destination, { flags: 'wx' });
@ -241,13 +243,13 @@ router.post('/download', jsonParser, async (request, response) => {
} }
// Move into asset place // 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.copyFileSync(temp_path, file_path);
fs.rmSync(temp_path); fs.rmSync(temp_path);
response.sendStatus(200); response.sendStatus(200);
} }
catch (error) { catch (error) {
console.log(error); console.error(error);
response.sendStatus(500); response.sendStatus(500);
} }
}); });
@ -270,7 +272,7 @@ router.post('/delete', jsonParser, async (request, response) => {
category = i; category = i;
if (category === null) { if (category === null) {
console.debug('Bad request: unsupported asset category.'); console.error('Bad request: unsupported asset category.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -280,25 +282,27 @@ router.post('/delete', jsonParser, async (request, response) => {
return response.status(400).send(validation.message); return response.status(400).send(validation.message);
const file_path = path.join(request.user.directories.assets, category, request.body.filename); 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 { try {
// Delete if previous download failed // Delete if previous download failed
if (fs.existsSync(file_path)) { if (fs.existsSync(file_path)) {
fs.unlink(file_path, (err) => { fs.unlink(file_path, (err) => {
if (err) throw err; if (err) {
throw err;
}
}); });
console.debug('Asset deleted.'); console.info('Asset deleted.');
} }
else { else {
console.debug('Asset not found.'); console.error('Asset not found.');
response.sendStatus(400); response.sendStatus(400);
} }
// Move into asset place // Move into asset place
response.sendStatus(200); response.sendStatus(200);
} }
catch (error) { catch (error) {
console.log(error); console.error(error);
response.sendStatus(500); response.sendStatus(500);
} }
}); });
@ -313,19 +317,24 @@ router.post('/delete', jsonParser, async (request, response) => {
* @returns {void} * @returns {void}
*/ */
router.post('/character', jsonParser, async (request, response) => { 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 // For backwards compatibility, don't reject invalid character names, just sanitize them
const name = sanitize(request.query.name.toString()); const name = sanitize(request.query.name.toString());
const inputCategory = request.query.category; const inputCategory = request.query.category;
// Check category // Check category
let category = null; let category = null;
for (let i of VALID_CATEGORIES) for (let i of VALID_CATEGORIES) {
if (i == inputCategory) if (i == inputCategory) {
category = i; category = i;
}
}
if (category === null) { if (category === null) {
console.debug('Bad request: unsupported asset category.'); console.error('Bad request: unsupported asset category.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -339,7 +348,9 @@ router.post('/character', jsonParser, async (request, response) => {
if (category == 'live2d') { if (category == 'live2d') {
const folders = fs.readdirSync(folderPath, { withFileTypes: true }); const folders = fs.readdirSync(folderPath, { withFileTypes: true });
for (const folderInfo of folders) { for (const folderInfo of folders) {
if (!folderInfo.isDirectory()) continue; if (!folderInfo.isDirectory()) {
continue;
}
const modelFolder = folderInfo.name; const modelFolder = folderInfo.name;
const live2dModelPath = path.join(folderPath, modelFolder); const live2dModelPath = path.join(folderPath, modelFolder);
@ -364,7 +375,7 @@ router.post('/character', jsonParser, async (request, response) => {
return response.send(output); return response.send(output);
} }
catch (err) { catch (err) {
console.log(err); console.error(err);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -230,7 +230,7 @@ async function sendScaleRequest(request, response) {
} }
const requestPrompt = convertTextCompletionPrompt(request.body.messages); const requestPrompt = convertTextCompletionPrompt(request.body.messages);
console.log('Scale request:', requestPrompt); console.debug('Scale request:', requestPrompt);
try { try {
const controller = new AbortController(); const controller = new AbortController();
@ -249,18 +249,18 @@ async function sendScaleRequest(request, response) {
}); });
if (!generateResponse.ok) { 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 }); return response.status(500).send({ error: true });
} }
/** @type {any} */ /** @type {any} */
const generateResponseJson = await generateResponse.json(); const generateResponseJson = await generateResponse.json();
console.log('Scale response:', generateResponseJson); console.debug('Scale response:', generateResponseJson);
const reply = { choices: [{ 'message': { 'content': generateResponseJson.output } }] }; const reply = { choices: [{ 'message': { 'content': generateResponseJson.output } }] };
return response.send(reply); return response.send(reply);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
if (!response.headersSent) { if (!response.headersSent) {
return response.status(500).send({ error: true }); 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); const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);
if (!request.body.reverse_proxy && !apiKey) { 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 }); return response.status(400).send({ error: true });
} }
@ -328,7 +328,7 @@ async function sendMakerSuiteRequest(request, response) {
} }
const body = getGeminiBody(); const body = getGeminiBody();
console.log('Google AI Studio request:', body); console.debug('Google AI Studio request:', body);
try { try {
const controller = new AbortController(); const controller = new AbortController();
@ -355,14 +355,14 @@ async function sendMakerSuiteRequest(request, response) {
// Pipe remote SSE stream to Express response // Pipe remote SSE stream to Express response
forwardFetchResponse(generateResponse, response); forwardFetchResponse(generateResponse, response);
} catch (error) { } catch (error) {
console.log('Error forwarding streaming response:', error); console.error('Error forwarding streaming response:', error);
if (!response.headersSent) { if (!response.headersSent) {
return response.status(500).send({ error: true }); return response.status(500).send({ error: true });
} }
} }
} else { } else {
if (!generateResponse.ok) { 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 }); 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; 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) { if (Array.isArray(responseContent?.parts) && isThinking && !showThoughts) {
responseContent.parts = responseContent.parts.filter(part => !part.thought); 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'); const responseText = typeof responseContent === 'string' ? responseContent : responseContent?.parts?.map(part => part.text)?.join('\n\n');
if (!responseText) { if (!responseText) {
let message = 'Google AI Studio Candidate text empty'; let message = 'Google AI Studio Candidate text empty';
console.log(message, generateResponseJson); console.error(message, generateResponseJson);
return response.send({ error: { message } }); return response.send({ error: { message } });
} }
@ -398,7 +398,7 @@ async function sendMakerSuiteRequest(request, response) {
return response.send(reply); return response.send(reply);
} }
} catch (error) { } 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) { if (!response.headersSent) {
return response.status(500).send({ error: true }); return response.status(500).send({ error: true });
} }
@ -411,9 +411,12 @@ async function sendMakerSuiteRequest(request, response) {
* @param {express.Response} response Express response * @param {express.Response} response Express response
*/ */
async function sendAI21Request(request, response) { async function sendAI21Request(request, response) {
if (!request.body) return response.sendStatus(400); if (!request.body) {
return response.sendStatus(400);
}
const controller = new AbortController(); const controller = new AbortController();
console.log(request.body.messages); console.debug(request.body.messages);
request.socket.removeAllListeners('close'); request.socket.removeAllListeners('close');
request.socket.on('close', function () { request.socket.on('close', function () {
controller.abort(); controller.abort();
@ -439,7 +442,7 @@ async function sendAI21Request(request, response) {
signal: controller.signal, signal: controller.signal,
}; };
console.log('AI21 request:', body); console.debug('AI21 request:', body);
try { try {
const generateResponse = await fetch(API_AI21 + '/chat/completions', options); const generateResponse = await fetch(API_AI21 + '/chat/completions', options);
@ -448,16 +451,16 @@ async function sendAI21Request(request, response) {
} else { } else {
if (!generateResponse.ok) { if (!generateResponse.ok) {
const errorText = await generateResponse.text(); 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 }; const errorJson = tryParse(errorText) ?? { error: true };
return response.status(500).send(errorJson); return response.status(500).send(errorJson);
} }
const generateResponseJson = await generateResponse.json(); const generateResponseJson = await generateResponse.json();
console.log('AI21 response:', generateResponseJson); console.debug('AI21 response:', generateResponseJson);
return response.send(generateResponseJson); return response.send(generateResponseJson);
} }
} catch (error) { } catch (error) {
console.log('Error communicating with AI21 API: ', error); console.error('Error communicating with AI21 API: ', error);
if (!response.headersSent) { if (!response.headersSent) {
response.send({ error: true }); response.send({ error: true });
} else { } 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); const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);
if (!apiKey) { if (!apiKey) {
console.log('MistralAI API key is missing.'); console.error('MistralAI API key is missing.');
return response.status(400).send({ error: true }); return response.status(400).send({ error: true });
} }
@ -517,7 +520,7 @@ async function sendMistralAIRequest(request, response) {
timeout: 0, timeout: 0,
}; };
console.log('MisralAI request:', requestBody); console.debug('MisralAI request:', requestBody);
const generateResponse = await fetch(apiUrl + '/chat/completions', config); const generateResponse = await fetch(apiUrl + '/chat/completions', config);
if (request.body.stream) { if (request.body.stream) {
@ -525,16 +528,16 @@ async function sendMistralAIRequest(request, response) {
} else { } else {
if (!generateResponse.ok) { if (!generateResponse.ok) {
const errorText = await generateResponse.text(); 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 }; const errorJson = tryParse(errorText) ?? { error: true };
return response.status(500).send(errorJson); return response.status(500).send(errorJson);
} }
const generateResponseJson = await generateResponse.json(); const generateResponseJson = await generateResponse.json();
console.log('MistralAI response:', generateResponseJson); console.debug('MistralAI response:', generateResponseJson);
return response.send(generateResponseJson); return response.send(generateResponseJson);
} }
} catch (error) { } catch (error) {
console.log('Error communicating with MistralAI API: ', error); console.error('Error communicating with MistralAI API: ', error);
if (!response.headersSent) { if (!response.headersSent) {
response.send({ error: true }); response.send({ error: true });
} else { } else {
@ -557,7 +560,7 @@ async function sendCohereRequest(request, response) {
}); });
if (!apiKey) { if (!apiKey) {
console.log('Cohere API key is missing.'); console.error('Cohere API key is missing.');
return response.status(400).send({ error: true }); return response.status(400).send({ error: true });
} }
@ -596,7 +599,7 @@ async function sendCohereRequest(request, response) {
requestBody.safety_mode = 'OFF'; requestBody.safety_mode = 'OFF';
} }
console.log('Cohere request:', requestBody); console.debug('Cohere request:', requestBody);
const config = { const config = {
method: 'POST', method: 'POST',
@ -618,16 +621,16 @@ async function sendCohereRequest(request, response) {
const generateResponse = await fetch(apiUrl, config); const generateResponse = await fetch(apiUrl, config);
if (!generateResponse.ok) { if (!generateResponse.ok) {
const errorText = await generateResponse.text(); 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 }; const errorJson = tryParse(errorText) ?? { error: true };
return response.status(500).send(errorJson); return response.status(500).send(errorJson);
} }
const generateResponseJson = await generateResponse.json(); const generateResponseJson = await generateResponse.json();
console.log('Cohere response:', generateResponseJson); console.debug('Cohere response:', generateResponseJson);
return response.send(generateResponseJson); return response.send(generateResponseJson);
} }
} catch (error) { } catch (error) {
console.log('Error communicating with Cohere API: ', error); console.error('Error communicating with Cohere API: ', error);
if (!response.headersSent) { if (!response.headersSent) {
response.send({ error: true }); response.send({ error: true });
} else { } 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); api_key_openai = readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);
headers = {}; headers = {};
} else { } 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 }); 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) { 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 }); 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) { } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) {
const models = data?.data; const models = data?.data;
console.log(models); console.info(models);
} else { } else {
const models = data?.data; const models = data?.data;
if (Array.isArray(models)) { if (Array.isArray(models)) {
const modelIds = models.filter(x => x && typeof x === 'object').map(x => x.id).sort(); 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 { } 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 { 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: [] } }); response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });
} }
} catch (e) { } catch (e) {
@ -755,8 +758,7 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o
}); });
router.post('/bias', jsonParser, async function (request, response) { router.post('/bias', jsonParser, async function (request, response) {
if (!request.body || !Array.isArray(request.body)) if (!request.body || !Array.isArray(request.body)) return response.sendStatus(400);
return response.sendStatus(400);
try { try {
const result = {}; const result = {};
@ -773,7 +775,7 @@ router.post('/bias', jsonParser, async function (request, response) {
const tokenizer = getSentencepiceTokenizer(model); const tokenizer = getSentencepiceTokenizer(model);
const instance = await tokenizer?.get(); const instance = await tokenizer?.get();
if (!instance) { if (!instance) {
console.warn('Tokenizer not initialized:', model); console.error('Tokenizer not initialized:', model);
return response.send({}); return response.send({});
} }
encodeFunction = (text) => new Uint32Array(instance.encodeIds(text)); 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); mergeObjectWithYaml(headers, request.body.custom_include_headers);
if (request.body.custom_prompt_post_processing) { 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 = postProcessPrompt(
request.body.messages, request.body.messages,
request.body.custom_prompt_post_processing, 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)); request.body.messages = postProcessPrompt(request.body.messages, 'deepseek', getPromptNames(request));
} else { } 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 }); return response.status(400).send({ error: true });
} }
if (!apiKey && !request.body.reverse_proxy && request.body.chat_completion_source !== CHAT_COMPLETION_SOURCES.CUSTOM) { 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 }); return response.status(400).send({ error: true });
} }
@ -1032,7 +1034,7 @@ router.post('/generate', jsonParser, function (request, response) {
signal: controller.signal, signal: controller.signal,
}; };
console.log(requestBody); console.debug(requestBody);
makeRequest(config, response, request); makeRequest(config, response, request);
@ -1049,7 +1051,7 @@ router.post('/generate', jsonParser, function (request, response) {
const fetchResponse = await fetch(endpointUrl, config); const fetchResponse = await fetch(endpointUrl, config);
if (request.body.stream) { if (request.body.stream) {
console.log('Streaming request in progress'); console.info('Streaming request in progress');
forwardFetchResponse(fetchResponse, response); forwardFetchResponse(fetchResponse, response);
return; return;
} }
@ -1058,10 +1060,10 @@ router.post('/generate', jsonParser, function (request, response) {
/** @type {any} */ /** @type {any} */
let json = await fetchResponse.json(); let json = await fetchResponse.json();
response.send(json); response.send(json);
console.log(json); console.debug(json);
console.log(json?.choices?.[0]?.message); console.debug(json?.choices?.[0]?.message);
} else if (fetchResponse.status === 429 && retries > 0) { } 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(() => { setTimeout(() => {
timeout *= 2; timeout *= 2;
makeRequest(config, response, request, retries - 1, timeout); makeRequest(config, response, request, retries - 1, timeout);
@ -1070,7 +1072,7 @@ router.post('/generate', jsonParser, function (request, response) {
await handleErrorResponse(fetchResponse); await handleErrorResponse(fetchResponse);
} }
} catch (error) { } catch (error) {
console.log('Generation failed', error); console.error('Generation failed', error);
const message = error.code === 'ECONNREFUSED' const message = error.code === 'ECONNREFUSED'
? `Connection refused: ${error.message}` ? `Connection refused: ${error.message}`
: error.message || 'Unknown error occurred'; : error.message || 'Unknown error occurred';
@ -1092,7 +1094,7 @@ router.post('/generate', jsonParser, function (request, response) {
const message = errorResponse.statusText || 'Unknown error occurred'; const message = errorResponse.statusText || 'Unknown error occurred';
const quota_error = errorResponse.status === 429 && errorData?.error?.type === 'insufficient_quota'; 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) { if (!response.headersSent) {
response.send({ error: { message }, quota_error: quota_error }); response.send({ error: { message }, quota_error: quota_error });

View File

@ -22,17 +22,17 @@ router.post('/generate', jsonParser, async function (request, response_generate)
request.socket.on('close', async function () { request.socket.on('close', async function () {
if (request.body.can_abort && !response_generate.writableEnded) { if (request.body.can_abort && !response_generate.writableEnded) {
try { try {
console.log('Aborting Kobold generation...'); console.info('Aborting Kobold generation...');
// send abort signal to koboldcpp // send abort signal to koboldcpp
const abortResponse = await fetch(`${request.body.api_server}/extra/abort`, { const abortResponse = await fetch(`${request.body.api_server}/extra/abort`, {
method: 'POST', method: 'POST',
}); });
if (!abortResponse.ok) { 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) { } catch (error) {
console.log(error); console.error(error);
} }
} }
controller.abort(); 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 = { const args = {
body: JSON.stringify(this_settings), body: JSON.stringify(this_settings),
headers: Object.assign( headers: Object.assign(
@ -105,7 +105,7 @@ router.post('/generate', jsonParser, async function (request, response_generate)
} else { } else {
if (!response.ok) { if (!response.ok) {
const errorText = await response.text(); 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 { try {
const errorJson = JSON.parse(errorText); const errorJson = JSON.parse(errorText);
@ -117,7 +117,7 @@ router.post('/generate', jsonParser, async function (request, response_generate)
} }
const data = await response.json(); const data = await response.json();
console.log('Endpoint response:', data); console.debug('Endpoint response:', data);
return response_generate.send(data); return response_generate.send(data);
} }
} catch (error) { } catch (error) {
@ -125,19 +125,19 @@ router.post('/generate', jsonParser, async function (request, response_generate)
switch (error?.status) { switch (error?.status) {
case 403: case 403:
case 503: // retry in case of temporary service issue, possibly caused by a queue failure? 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); await delay(delayAmount);
break; break;
default: default:
if ('status' in error) { 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 }); 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 }); return response_generate.send({ error: true });
}); });
@ -193,16 +193,17 @@ router.post('/transcribe-audio', urlencodedParser, async function (request, resp
const server = request.body.server; const server = request.body.server;
if (!server) { if (!server) {
console.log('Server is not set'); console.error('Server is not set');
return response.sendStatus(400); return response.sendStatus(400);
} }
if (!request.file) { if (!request.file) {
console.log('No audio file found'); console.error('No audio file found');
return response.sendStatus(400); 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'); const fileBase64 = fs.readFileSync(request.file.path).toString('base64');
fs.rmSync(request.file.path); fs.rmSync(request.file.path);
@ -226,12 +227,12 @@ router.post('/transcribe-audio', urlencodedParser, async function (request, resp
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); return response.status(500).send(text);
} }
const data = await result.json(); const data = await result.json();
console.log('KoboldCpp transcription response', data); console.debug('KoboldCpp transcription response', data);
return response.json(data); return response.json(data);
} catch (error) { } catch (error) {
console.error('KoboldCpp transcription failed', error); console.error('KoboldCpp transcription failed', error);

View File

@ -13,7 +13,7 @@ router.post('/generate', jsonParser, async function (request, response) {
const cookie = readSecret(request.user.directories, SECRET_KEYS.SCALE_COOKIE); const cookie = readSecret(request.user.directories, SECRET_KEYS.SCALE_COOKIE);
if (!cookie) { if (!cookie) {
console.log('No Scale cookie found'); console.error('No Scale cookie found');
return response.sendStatus(400); 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', { const result = await fetch('https://dashboard.scale.com/spellbook/api/trpc/v2.variant.run', {
method: 'POST', method: 'POST',
@ -75,7 +75,7 @@ router.post('/generate', jsonParser, async function (request, response) {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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 } }); 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 data = await result.json();
const output = data?.result?.data?.json?.outputs?.[0] || ''; const output = data?.result?.data?.json?.outputs?.[0] || '';
console.log('Scale response:', data); console.debug('Scale response:', data);
if (!output) { if (!output) {
console.warn('Scale response is empty'); console.warn('Scale response is empty');
@ -92,7 +92,7 @@ router.post('/generate', jsonParser, async function (request, response) {
return response.json({ output }); return response.json({ output });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -58,12 +58,12 @@ async function parseOllamaStream(jsonStream, request, response) {
}); });
jsonStream.body.on('end', () => { jsonStream.body.on('end', () => {
console.log('Streaming request finished'); console.info('Streaming request finished');
response.write('data: [DONE]\n\n'); response.write('data: [DONE]\n\n');
response.end(); response.end();
}); });
} catch (error) { } catch (error) {
console.log('Error forwarding streaming response:', error); console.error('Error forwarding streaming response:', error);
if (!response.headersSent) { if (!response.headersSent) {
return response.status(500).send({ error: true }); return response.status(500).send({ error: true });
} else { } else {
@ -79,16 +79,16 @@ async function parseOllamaStream(jsonStream, request, response) {
*/ */
async function abortKoboldCppRequest(url) { async function abortKoboldCppRequest(url) {
try { try {
console.log('Aborting Kobold generation...'); console.info('Aborting Kobold generation...');
const abortResponse = await fetch(`${url}/api/extra/abort`, { const abortResponse = await fetch(`${url}/api/extra/abort`, {
method: 'POST', method: 'POST',
}); });
if (!abortResponse.ok) { 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) { } 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'); 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 baseUrl = trimV1(request.body.api_server);
const args = { const args = {
@ -123,6 +124,7 @@ router.post('/status', jsonParser, async function (request, response) {
case TEXTGEN_TYPES.LLAMACPP: case TEXTGEN_TYPES.LLAMACPP:
case TEXTGEN_TYPES.INFERMATICAI: case TEXTGEN_TYPES.INFERMATICAI:
case TEXTGEN_TYPES.OPENROUTER: case TEXTGEN_TYPES.OPENROUTER:
case TEXTGEN_TYPES.FEATHERLESS:
url += '/v1/models'; url += '/v1/models';
break; break;
case TEXTGEN_TYPES.DREAMGEN: case TEXTGEN_TYPES.DREAMGEN:
@ -140,9 +142,6 @@ router.post('/status', jsonParser, async function (request, response) {
case TEXTGEN_TYPES.OLLAMA: case TEXTGEN_TYPES.OLLAMA:
url += '/api/tags'; url += '/api/tags';
break; break;
case TEXTGEN_TYPES.FEATHERLESS:
url += '/v1/models';
break;
case TEXTGEN_TYPES.HUGGINGFACE: case TEXTGEN_TYPES.HUGGINGFACE:
url += '/info'; url += '/info';
break; break;
@ -152,7 +151,7 @@ router.post('/status', jsonParser, async function (request, response) {
const isPossiblyLmStudio = modelsReply.headers.get('x-powered-by') === 'Express'; const isPossiblyLmStudio = modelsReply.headers.get('x-powered-by') === 'Express';
if (!modelsReply.ok) { if (!modelsReply.ok) {
console.log('Models endpoint is offline.'); console.error('Models endpoint is offline.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -173,12 +172,12 @@ router.post('/status', jsonParser, async function (request, response) {
} }
if (!Array.isArray(data.data)) { 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); return response.sendStatus(400);
} }
const modelIds = data.data.map(x => x.id); 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 // Set result to the first model ID
result = modelIds[0] || 'Valid'; result = modelIds[0] || 'Valid';
@ -191,7 +190,7 @@ router.post('/status', jsonParser, async function (request, response) {
if (modelInfoReply.ok) { if (modelInfoReply.ok) {
/** @type {any} */ /** @type {any} */
const modelInfo = await modelInfoReply.json(); const modelInfo = await modelInfoReply.json();
console.log('Ooba model info:', modelInfo); console.debug('Ooba model info:', modelInfo);
const modelName = modelInfo?.model_name; const modelName = modelInfo?.model_name;
result = modelName || result; result = modelName || result;
@ -208,7 +207,7 @@ router.post('/status', jsonParser, async function (request, response) {
if (modelInfoReply.ok) { if (modelInfoReply.ok) {
/** @type {any} */ /** @type {any} */
const modelInfo = await modelInfoReply.json(); const modelInfo = await modelInfoReply.json();
console.log('Tabby model info:', modelInfo); console.debug('Tabby model info:', modelInfo);
const modelName = modelInfo?.id; const modelName = modelInfo?.id;
result = modelName || result; result = modelName || result;
@ -230,7 +229,9 @@ router.post('/status', jsonParser, async function (request, response) {
}); });
router.post('/props', 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 { try {
const baseUrl = trimV1(request.body.api_server); 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'] = props['chat_template'].slice(0, -1) + '\n';
} }
props['chat_template_hash'] = createHash('sha256').update(props['chat_template']).digest('hex'); 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); return response.send(props);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -264,7 +265,9 @@ router.post('/props', jsonParser, async function (request, response) {
}); });
router.post('/generate', 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 { try {
if (request.body.api_server.indexOf('localhost') !== -1) { 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 apiType = request.body.api_type;
const baseUrl = request.body.api_server; const baseUrl = request.body.api_server;
console.log(request.body); console.debug(request.body);
const controller = new AbortController(); const controller = new AbortController();
request.socket.removeAllListeners('close'); request.socket.removeAllListeners('close');
@ -399,7 +402,7 @@ router.post('/generate', jsonParser, async function (request, response) {
if (completionsReply.ok) { if (completionsReply.ok) {
/** @type {any} */ /** @type {any} */
const data = await completionsReply.json(); const data = await completionsReply.json();
console.log('Endpoint response:', data); console.debug('Endpoint response:', data);
// Map InfermaticAI response to OAI completions format // Map InfermaticAI response to OAI completions format
if (apiType === TEXTGEN_TYPES.INFERMATICAI) { if (apiType === TEXTGEN_TYPES.INFERMATICAI) {
@ -411,24 +414,20 @@ router.post('/generate', jsonParser, async function (request, response) {
const text = await completionsReply.text(); const text = await completionsReply.text();
const errorBody = { error: true, status: completionsReply.status, response: text }; const errorBody = { error: true, status: completionsReply.status, response: text };
if (!response.headersSent) { return !response.headersSent
return response.send(errorBody); ? response.send(errorBody)
} : response.end();
return response.end();
} }
} }
} catch (error) { } catch (error) {
const status = error?.status ?? error?.code ?? 'UNKNOWN'; const status = error?.status ?? error?.code ?? 'UNKNOWN';
const text = error?.error ?? error?.statusText ?? error?.message ?? 'Unknown error on /generate endpoint'; const text = error?.error ?? error?.statusText ?? error?.message ?? 'Unknown error on /generate endpoint';
let value = { error: true, status: status, response: text }; let value = { error: true, status: status, response: text };
console.log('Endpoint error:', error); console.error('Endpoint error:', error);
if (!response.headersSent) { return !response.headersSent
return response.send(value); ? response.send(value)
} : response.end();
return response.end();
} }
}); });
@ -436,7 +435,9 @@ const ollama = express.Router();
ollama.post('/download', jsonParser, async function (request, response) { ollama.post('/download', jsonParser, async function (request, response) {
try { 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 name = request.body.name;
const url = String(request.body.api_server).replace(/\/$/, ''); const url = String(request.body.api_server).replace(/\/$/, '');
@ -451,7 +452,7 @@ ollama.post('/download', jsonParser, async function (request, response) {
}); });
if (!fetchResponse.ok) { 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 }); 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); 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 baseUrl = trimV1(request.body.server_url);
const fetchResponse = await fetch(`${baseUrl}/api/generate`, { const fetchResponse = await fetch(`${baseUrl}/api/generate`, {
@ -483,18 +484,18 @@ ollama.post('/caption-image', jsonParser, async function (request, response) {
}); });
if (!fetchResponse.ok) { 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 }); return response.status(500).send({ error: true });
} }
/** @type {any} */ /** @type {any} */
const data = await fetchResponse.json(); const data = await fetchResponse.json();
console.log('Ollama caption response:', data); console.debug('Ollama caption response:', data);
const caption = data?.response || ''; const caption = data?.response || '';
if (!caption) { if (!caption) {
console.log('Ollama caption is empty.'); console.error('Ollama caption is empty.');
return response.status(500).send({ error: true }); return response.status(500).send({ error: true });
} }
@ -513,7 +514,7 @@ llamacpp.post('/caption-image', jsonParser, async function (request, response) {
return response.sendStatus(400); 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 baseUrl = trimV1(request.body.server_url);
const fetchResponse = await fetch(`${baseUrl}/completion`, { const fetchResponse = await fetch(`${baseUrl}/completion`, {
@ -529,18 +530,18 @@ llamacpp.post('/caption-image', jsonParser, async function (request, response) {
}); });
if (!fetchResponse.ok) { 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 }); return response.status(500).send({ error: true });
} }
/** @type {any} */ /** @type {any} */
const data = await fetchResponse.json(); const data = await fetchResponse.json();
console.log('LlamaCpp caption response:', data); console.debug('LlamaCpp caption response:', data);
const caption = data?.content || ''; const caption = data?.content || '';
if (!caption) { if (!caption) {
console.log('LlamaCpp caption is empty.'); console.error('LlamaCpp caption is empty.');
return response.status(500).send({ error: true }); return response.status(500).send({ error: true });
} }
@ -558,7 +559,7 @@ llamacpp.post('/props', jsonParser, async function (request, response) {
return response.sendStatus(400); 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 baseUrl = trimV1(request.body.server_url);
const fetchResponse = await fetch(`${baseUrl}/props`, { const fetchResponse = await fetch(`${baseUrl}/props`, {
@ -566,12 +567,12 @@ llamacpp.post('/props', jsonParser, async function (request, response) {
}); });
if (!fetchResponse.ok) { 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 }); return response.status(500).send({ error: true });
} }
const data = await fetchResponse.json(); const data = await fetchResponse.json();
console.log('LlamaCpp props response:', data); console.debug('LlamaCpp props response:', data);
return response.send(data); return response.send(data);
@ -590,7 +591,7 @@ llamacpp.post('/slots', jsonParser, async function (request, response) {
return response.sendStatus(400); 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); const baseUrl = trimV1(request.body.server_url);
let fetchResponse; let fetchResponse;
@ -616,12 +617,12 @@ llamacpp.post('/slots', jsonParser, async function (request, response) {
} }
if (!fetchResponse.ok) { 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 }); return response.status(500).send({ error: true });
} }
const data = await fetchResponse.json(); const data = await fetchResponse.json();
console.log('LlamaCpp slots response:', data); console.debug('LlamaCpp slots response:', data);
return response.send(data); return response.send(data);
@ -659,14 +660,14 @@ tabby.post('/download', jsonParser, async function (request, response) {
return response.status(403).send({ error: true }); return response.status(403).send({ error: true });
} }
} else { } 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 }); return response.status(permissionResponse.status).send({ error: true });
} }
const fetchResponse = await fetch(`${baseUrl}/v1/download`, args); const fetchResponse = await fetch(`${baseUrl}/v1/download`, args);
if (!fetchResponse.ok) { 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 }); return response.status(fetchResponse.status).send({ error: true });
} }

View File

@ -26,7 +26,7 @@ router.post('/delete', jsonParser, function (request, response) {
const fileName = path.join(request.user.directories.backgrounds, sanitize(request.body.bg)); const fileName = path.join(request.user.directories.backgrounds, sanitize(request.body.bg));
if (!fs.existsSync(fileName)) { if (!fs.existsSync(fileName)) {
console.log('BG file not found'); console.error('BG file not found');
return response.sendStatus(400); 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)); const newFileName = path.join(request.user.directories.backgrounds, sanitize(request.body.new_bg));
if (!fs.existsSync(oldFileName)) { if (!fs.existsSync(oldFileName)) {
console.log('BG file not found'); console.error('BG file not found');
return response.sendStatus(400); return response.sendStatus(400);
} }
if (fs.existsSync(newFileName)) { if (fs.existsSync(newFileName)) {
console.log('New BG file already exists'); console.error('New BG file already exists');
return response.sendStatus(400); return response.sendStatus(400);
} }

View File

@ -2,10 +2,10 @@ import express from 'express';
import { jsonParser } from '../express-common.js'; import { jsonParser } from '../express-common.js';
import { getPipeline, getRawImage } from '../transformers.js'; import { getPipeline, getRawImage } from '../transformers.js';
const TASK = 'image-to-text';
export const router = express.Router(); export const router = express.Router();
const TASK = 'image-to-text';
router.post('/', jsonParser, async (req, res) => { router.post('/', jsonParser, async (req, res) => {
try { try {
const { image } = req.body; const { image } = req.body;
@ -13,14 +13,14 @@ router.post('/', jsonParser, async (req, res) => {
const rawImage = await getRawImage(image); const rawImage = await getRawImage(image);
if (!rawImage) { if (!rawImage) {
console.log('Failed to parse captioned image'); console.error('Failed to parse captioned image');
return res.sendStatus(400); return res.sendStatus(400);
} }
const pipe = await getPipeline(TASK); const pipe = await getPipeline(TASK);
const result = await pipe(rawImage); const result = await pipe(rawImage);
const text = result[0].generated_text; const text = result[0].generated_text;
console.log('Image caption:', text); console.debug('Image caption:', text);
return res.json({ caption: text }); return res.json({ caption: text });
} catch (error) { } catch (error) {

View File

@ -90,7 +90,7 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u
writeFileAtomicSync(outputImagePath, outputImage); writeFileAtomicSync(outputImagePath, outputImage);
return true; return true;
} catch (err) { } catch (err) {
console.log(err); console.error(err);
return false; 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 // If it's an unsupported type of image (APNG) - just read the file as buffer
catch (error) { catch (error) {
console.log(`Failed to read image: ${imgPath}`, error); console.error(`Failed to read image: ${imgPath}`, error);
return fs.readFileSync(imgPath); return fs.readFileSync(imgPath);
} }
} }
@ -222,12 +222,12 @@ const processCharacter = async (item, directories) => {
return character; return character;
} }
catch (err) { catch (err) {
console.log(`Could not process character: ${item}`); console.error(`Could not process character: ${item}`);
if (err instanceof SyntaxError) { 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 { } else {
console.log('An unexpected error occurred: ', err); console.error('An unexpected error occurred: ', err);
} }
return { return {
@ -315,7 +315,7 @@ function readFromV2(char) {
}; };
_.forEach(fieldMappings, (v2Path, charField) => { _.forEach(fieldMappings, (v2Path, charField) => {
//console.log(`Migrating field: ${charField} from ${v2Path}`); //console.info(`Migrating field: ${charField} from ${v2Path}`);
const v2Value = _.get(char.data, v2Path); const v2Value = _.get(char.data, v2Path);
if (_.isUndefined(v2Value)) { if (_.isUndefined(v2Value)) {
let defaultValue = undefined; let defaultValue = undefined;
@ -330,15 +330,15 @@ function readFromV2(char) {
} }
if (!_.isUndefined(defaultValue)) { 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; char[charField] = defaultValue;
} else { } 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; return;
} }
} }
if (!_.isUndefined(char[charField]) && !_.isUndefined(v2Value) && String(char[charField]) !== String(v2Value)) { 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; char[charField] = v2Value;
}); });
@ -435,7 +435,7 @@ function charaFormatData(data, directories) {
} }
} catch { } 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 // Deep merge the extensions object
_.set(char, 'data.extensions', deepMerge(char.data.extensions, extensions)); _.set(char, 'data.extensions', deepMerge(char.data.extensions, extensions));
} catch { } 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'); const fileText = fs.readFileSync(uploadPath, 'utf8');
fs.rmSync(uploadPath); fs.rmSync(uploadPath);
const yamlData = yaml.parse(fileText); const yamlData = yaml.parse(fileText);
console.log('Importing from YAML'); console.info('Importing from YAML');
yamlData.name = sanitize(yamlData.name); yamlData.name = sanitize(yamlData.name);
const fileName = preservedFileName || getPngName(yamlData.name, context.request.user.directories); const fileName = preservedFileName || getPngName(yamlData.name, context.request.user.directories);
let char = convertToV2({ let char = convertToV2({
@ -552,7 +552,7 @@ async function importFromYaml(uploadPath, context, preservedFileName) {
async function importFromCharX(uploadPath, { request }, preservedFileName) { async function importFromCharX(uploadPath, { request }, preservedFileName) {
const data = fs.readFileSync(uploadPath).buffer; const data = fs.readFileSync(uploadPath).buffer;
fs.rmSync(uploadPath); fs.rmSync(uploadPath);
console.log('Importing from CharX'); console.info('Importing from CharX');
const cardBuffer = await extractFileFromZipBuffer(data, 'card.json'); const cardBuffer = await extractFileFromZipBuffer(data, 'card.json');
if (!cardBuffer) { if (!cardBuffer) {
@ -601,7 +601,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) {
let jsonData = JSON.parse(data); let jsonData = JSON.parse(data);
if (jsonData.spec !== undefined) { if (jsonData.spec !== undefined) {
console.log(`Importing from ${jsonData.spec} json`); console.info(`Importing from ${jsonData.spec} json`);
importRisuSprites(request.user.directories, jsonData); importRisuSprites(request.user.directories, jsonData);
unsetFavFlag(jsonData); unsetFavFlag(jsonData);
jsonData = readFromV2(jsonData); jsonData = readFromV2(jsonData);
@ -611,7 +611,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) {
const result = await writeCharacterData(defaultAvatarPath, char, pngName, request); const result = await writeCharacterData(defaultAvatarPath, char, pngName, request);
return result ? pngName : ''; return result ? pngName : '';
} else if (jsonData.name !== undefined) { } else if (jsonData.name !== undefined) {
console.log('Importing from v1 json'); console.info('Importing from v1 json');
jsonData.name = sanitize(jsonData.name); jsonData.name = sanitize(jsonData.name);
if (jsonData.creator_notes) { if (jsonData.creator_notes) {
jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); 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); const result = await writeCharacterData(defaultAvatarPath, charJSON, pngName, request);
return result ? pngName : ''; return result ? pngName : '';
} else if (jsonData.char_name !== undefined) {//json Pygmalion notepad } 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); jsonData.char_name = sanitize(jsonData.char_name);
if (jsonData.creator_notes) { if (jsonData.creator_notes) {
jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); 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); const pngName = preservedFileName || getPngName(jsonData.name, request.user.directories);
if (jsonData.spec !== undefined) { 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); importRisuSprites(request.user.directories, jsonData);
unsetFavFlag(jsonData); unsetFavFlag(jsonData);
jsonData = readFromV2(jsonData); jsonData = readFromV2(jsonData);
@ -694,7 +694,7 @@ async function importFromPng(uploadPath, { request }, preservedFileName) {
fs.unlinkSync(uploadPath); fs.unlinkSync(uploadPath);
return result ? pngName : ''; return result ? pngName : '';
} else if (jsonData.name !== undefined) { } else if (jsonData.name !== undefined) {
console.log('Found a v1 character file.'); console.info('Found a v1 character file.');
if (jsonData.creator_notes) { if (jsonData.creator_notes) {
jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); 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} * @returns {void}
*/ */
router.post('/edit-attribute', jsonParser, async function (request, response) { router.post('/edit-attribute', jsonParser, async function (request, response) {
console.log(request.body); console.debug(request.body);
if (!request.body) { if (!request.body) {
console.error('Error: no response body detected'); console.error('Error: no response body detected');
return response.status(400).send('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); await writeCharacterData(avatarPath, JSON.stringify(character), targetImg, request);
response.sendStatus(200); response.sendStatus(200);
} else { } else {
console.log(validator.lastValidationError); console.error(validator.lastValidationError);
response.status(400).send({ message: `Validation failed for ${character.name}`, error: validator.lastValidationError }); response.status(400).send({ message: `Validation failed for ${character.name}`, error: validator.lastValidationError });
} }
} catch (exception) { } catch (exception) {
@ -1043,7 +1043,7 @@ router.post('/chats', jsonParser, async function (request, response) {
const fileSizeInKB = `${(stats.size / 1024).toFixed(2)}kb`; const fileSizeInKB = `${(stats.size / 1024).toFixed(2)}kb`;
if (stats.size === 0) { if (stats.size === 0) {
console.log(`Found an empty chat file: ${pathToFile}`); console.warn(`Found an empty chat file: ${pathToFile}`);
res({}); res({});
return; return;
} }
@ -1075,7 +1075,7 @@ router.post('/chats', jsonParser, async function (request, response) {
res(chatData); res(chatData);
} else { } else {
console.log('Found an invalid or corrupted chat file:', pathToFile); console.warn('Found an invalid or corrupted chat file:', pathToFile);
res({}); res({});
} }
} }
@ -1088,7 +1088,7 @@ router.post('/chats', jsonParser, async function (request, response) {
return response.send(validFiles); return response.send(validFiles);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ error: true }); return response.send({ error: true });
} }
}); });
@ -1155,7 +1155,7 @@ router.post('/import', urlencodedParser, async function (request, response) {
response.send({ file_name: fileName }); response.send({ file_name: fileName });
} catch (err) { } catch (err) {
console.log(err); console.error(err);
response.send({ error: true }); response.send({ error: true });
} }
}); });
@ -1163,14 +1163,13 @@ router.post('/import', urlencodedParser, async function (request, response) {
router.post('/duplicate', jsonParser, async function (request, response) { router.post('/duplicate', jsonParser, async function (request, response) {
try { try {
if (!request.body.avatar_url) { if (!request.body.avatar_url) {
console.log('avatar URL not found in request body'); console.error('avatar URL not found in request body');
console.log(request.body); console.debug(request.body);
return response.sendStatus(400); return response.sendStatus(400);
} }
let filename = path.join(request.user.directories.characters, sanitize(request.body.avatar_url)); let filename = path.join(request.user.directories.characters, sanitize(request.body.avatar_url));
if (!fs.existsSync(filename)) { if (!fs.existsSync(filename)) {
console.log('file for dupe not found'); console.error('file for dupe not found', filename);
console.log(filename);
return response.sendStatus(404); return response.sendStatus(404);
} }
let suffix = 1; let suffix = 1;
@ -1198,7 +1197,7 @@ router.post('/duplicate', jsonParser, async function (request, response) {
} }
fs.copyFileSync(filename, newFilename); 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 }); response.send({ path: path.parse(newFilename).base });
} }
catch (error) { catch (error) {

View File

@ -49,7 +49,7 @@ function backupChat(directory, name, chat) {
removeOldBackups(directory, 'chat_', maxTotalChatBackups); removeOldBackups(directory, 'chat_', maxTotalChatBackups);
} catch (err) { } 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); getBackupFunction(request.user.profile.handle)(request.user.directories.backups, directoryName, jsonlData);
return response.send({ result: 'ok' }); return response.send({ result: 'ok' });
} catch (error) { } catch (error) {
response.send(error); console.error(error);
return console.log(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 pathToOriginalFile = path.join(pathToFolder, sanitize(request.body.original_file));
const pathToRenamedFile = path.join(pathToFolder, sanitize(request.body.renamed_file)); const pathToRenamedFile = path.join(pathToFolder, sanitize(request.body.renamed_file));
const sanitizedFileName = path.parse(pathToRenamedFile).name; const sanitizedFileName = path.parse(pathToRenamedFile).name;
console.log('Old chat name', pathToOriginalFile); console.info('Old chat name', pathToOriginalFile);
console.log('New chat name', pathToRenamedFile); console.info('New chat name', pathToRenamedFile);
if (!fs.existsSync(pathToOriginalFile) || fs.existsSync(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 }); return response.status(400).send({ error: true });
} }
fs.copyFileSync(pathToOriginalFile, pathToRenamedFile); fs.copyFileSync(pathToOriginalFile, pathToRenamedFile);
fs.rmSync(pathToOriginalFile); fs.rmSync(pathToOriginalFile);
console.log('Successfully renamed.'); console.info('Successfully renamed.');
return response.send({ ok: true, sanitizedFileName }); return response.send({ ok: true, sanitizedFileName });
}); });
@ -351,12 +351,12 @@ router.post('/delete', jsonParser, function (request, response) {
const chatFileExists = fs.existsSync(filePath); const chatFileExists = fs.existsSync(filePath);
if (!chatFileExists) { if (!chatFileExists) {
console.log(`Chat file not found '${filePath}'`); console.error(`Chat file not found '${filePath}'`);
return response.sendStatus(400); return response.sendStatus(400);
} }
fs.rmSync(filePath); fs.rmSync(filePath);
console.log('Deleted chat file: ' + filePath); console.info(`Deleted chat file: ${filePath}`);
return response.send('ok'); return response.send('ok');
}); });
@ -373,7 +373,7 @@ router.post('/export', jsonParser, async function (request, response) {
const errorMessage = { const errorMessage = {
message: `Could not find JSONL file to export. Source chat file: ${filename}.`, 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); return response.status(404).json(errorMessage);
} }
try { try {
@ -386,14 +386,14 @@ router.post('/export', jsonParser, async function (request, response) {
result: rawFile, result: rawFile,
}; };
console.log(`Chat exported as ${exportfilename}`); console.info(`Chat exported as ${exportfilename}`);
return response.status(200).json(successMessage); return response.status(200).json(successMessage);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
const errorMessage = { const errorMessage = {
message: `Could not read JSONL file to export. Source chat file: ${filename}.`, 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); return response.status(500).json(errorMessage);
} }
} }
@ -420,12 +420,11 @@ router.post('/export', jsonParser, async function (request, response) {
message: `Chat saved to ${exportfilename}`, message: `Chat saved to ${exportfilename}`,
result: buffer, result: buffer,
}; };
console.log(`Chat exported as ${exportfilename}`); console.info(`Chat exported as ${exportfilename}`);
return response.status(200).json(successMessage); return response.status(200).json(successMessage);
}); });
} catch (err) { } catch (err) {
console.log('chat export failed.'); console.error('chat export failed.', err);
console.log(err);
return response.sendStatus(400); return response.sendStatus(400);
} }
}); });
@ -482,7 +481,7 @@ router.post('/import', urlencodedParser, function (request, response) {
} else if (Array.isArray(jsonData.messages)) { // Agnai's format } else if (Array.isArray(jsonData.messages)) { // Agnai's format
importFunc = importAgnaiChat; importFunc = importAgnaiChat;
} else { // Unknown format } else { // Unknown format
console.log('Incorrect chat format .json'); console.error('Incorrect chat format .json');
return response.send({ error: true }); return response.send({ error: true });
} }
@ -510,7 +509,7 @@ router.post('/import', urlencodedParser, function (request, response) {
const jsonData = JSON.parse(header); const jsonData = JSON.parse(header);
if (!(jsonData.user_name !== undefined || jsonData.name !== undefined)) { 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 }); return response.send({ error: true });
} }
@ -616,7 +615,7 @@ router.post('/search', jsonParser, function (request, response) {
break; break;
} }
} catch (error) { } catch (error) {
console.error(groupFile, 'group file is corrupted:', error); console.warn(groupFile, 'group file is corrupted:', error);
} }
} }

View File

@ -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); const result = await getResult(text);
console.log('Classify output:', result); console.debug('Classify output:', result);
return res.json({ classification: result }); return res.json({ classification: result });
} catch (error) { } catch (error) {

View File

@ -71,7 +71,7 @@ export function getDefaultPresets(directories) {
return presets; return presets;
} catch (err) { } catch (err) {
console.log('Failed to get default presets', err); console.warn('Failed to get default presets', err);
return []; return [];
} }
} }
@ -92,7 +92,7 @@ export function getDefaultPresetFile(filename) {
const fileContent = fs.readFileSync(contentPath, 'utf8'); const fileContent = fs.readFileSync(contentPath, 'utf8');
return JSON.parse(fileContent); return JSON.parse(fileContent);
} catch (err) { } catch (err) {
console.log(`Failed to get default file ${filename}`, err); console.warn(`Failed to get default file ${filename}`, err);
return null; return null;
} }
} }
@ -121,21 +121,21 @@ async function seedContentForUser(contentIndex, directories, forceCategories) {
} }
if (!contentItem.folder) { if (!contentItem.folder) {
console.log(`Content file ${contentItem.filename} has no parent folder`); console.warn(`Content file ${contentItem.filename} has no parent folder`);
continue; continue;
} }
const contentPath = path.join(contentItem.folder, contentItem.filename); const contentPath = path.join(contentItem.folder, contentItem.filename);
if (!fs.existsSync(contentPath)) { if (!fs.existsSync(contentPath)) {
console.log(`Content file ${contentItem.filename} is missing`); console.warn(`Content file ${contentItem.filename} is missing`);
continue; continue;
} }
const contentTarget = getTargetByType(contentItem.type, directories); const contentTarget = getTargetByType(contentItem.type, directories);
if (!contentTarget) { 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; continue;
} }
@ -144,12 +144,12 @@ async function seedContentForUser(contentIndex, directories, forceCategories) {
contentLog.push(contentItem.filename); contentLog.push(contentItem.filename);
if (fs.existsSync(targetPath)) { 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; continue;
} }
fs.cpSync(contentPath, targetPath, { recursive: true, force: false }); 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; anyContentAdded = true;
} }
@ -182,12 +182,12 @@ export async function checkForNewContent(directoriesList, forceCategories = [])
} }
if (anyContentAdded && !contentCheckSkip && forceCategories?.length === 0) { if (anyContentAdded && !contentCheckSkip && forceCategories?.length === 0) {
console.log(); console.info();
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.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.log(); console.info();
} }
} catch (err) { } 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) { if (!result.ok) {
const text = await result.text(); 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'); throw new Error('Failed to download lorebook');
} }
@ -355,7 +355,7 @@ async function downloadChubCharacter(id) {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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'); throw new Error('Failed to download character');
} }
@ -376,7 +376,7 @@ async function downloadPygmalionCharacter(id) {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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'); 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'); throw new Error('Failed to download character');
} }
@ -577,7 +577,7 @@ async function downloadRisuCharacter(uuid) {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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'); throw new Error('Failed to download character');
} }
@ -673,11 +673,11 @@ router.post('/importURL', jsonParser, async (request, response) => {
type = chubParsed?.type; type = chubParsed?.type;
if (chubParsed?.type === 'character') { if (chubParsed?.type === 'character') {
console.log('Downloading chub character:', chubParsed.id); console.info('Downloading chub character:', chubParsed.id);
result = await downloadChubCharacter(chubParsed.id); result = await downloadChubCharacter(chubParsed.id);
} }
else if (chubParsed?.type === 'lorebook') { else if (chubParsed?.type === 'lorebook') {
console.log('Downloading chub lorebook:', chubParsed.id); console.info('Downloading chub lorebook:', chubParsed.id);
result = await downloadChubLorebook(chubParsed.id); result = await downloadChubLorebook(chubParsed.id);
} }
else { else {
@ -692,7 +692,7 @@ router.post('/importURL', jsonParser, async (request, response) => {
type = 'character'; type = 'character';
result = await downloadRisuCharacter(uuid); result = await downloadRisuCharacter(uuid);
} else if (isGeneric) { } else if (isGeneric) {
console.log('Downloading from generic url.'); console.info('Downloading from generic url.');
type = 'character'; type = 'character';
result = await downloadGenericPng(url); result = await downloadGenericPng(url);
} else { } else {
@ -708,7 +708,7 @@ router.post('/importURL', jsonParser, async (request, response) => {
response.set('X-Custom-Content-Type', type); response.set('X-Custom-Content-Type', type);
return response.send(result.buffer); return response.send(result.buffer);
} catch (error) { } catch (error) {
console.log('Importing custom content failed', error); console.error('Importing custom content failed', error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -728,22 +728,22 @@ router.post('/importUUID', jsonParser, async (request, response) => {
const uuidType = uuid.includes('lorebook') ? 'lorebook' : 'character'; const uuidType = uuid.includes('lorebook') ? 'lorebook' : 'character';
if (isPygmalion) { if (isPygmalion) {
console.log('Downloading Pygmalion character:', uuid); console.info('Downloading Pygmalion character:', uuid);
result = await downloadPygmalionCharacter(uuid); result = await downloadPygmalionCharacter(uuid);
} else if (isJannny) { } 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]); result = await downloadJannyCharacter(uuid.split('_')[0]);
} else if (isAICC) { } else if (isAICC) {
const [, author, card] = uuid.split('/'); const [, author, card] = uuid.split('/');
console.log('Downloading AICC character:', `${author}/${card}`); console.info('Downloading AICC character:', `${author}/${card}`);
result = await downloadAICCCharacter(`${author}/${card}`); result = await downloadAICCCharacter(`${author}/${card}`);
} else { } else {
if (uuidType === 'character') { if (uuidType === 'character') {
console.log('Downloading chub character:', uuid); console.info('Downloading chub character:', uuid);
result = await downloadChubCharacter(uuid); result = await downloadChubCharacter(uuid);
} }
else if (uuidType === 'lorebook') { else if (uuidType === 'lorebook') {
console.log('Downloading chub lorebook:', uuid); console.info('Downloading chub lorebook:', uuid);
result = await downloadChubLorebook(uuid); result = await downloadChubLorebook(uuid);
} }
else { else {
@ -756,7 +756,7 @@ router.post('/importUUID', jsonParser, async (request, response) => {
response.set('X-Custom-Content-Type', uuidType); response.set('X-Custom-Content-Type', uuidType);
return response.send(result.buffer); return response.send(result.buffer);
} catch (error) { } catch (error) {
console.log('Importing custom content failed', error); console.error('Importing custom content failed', error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -80,7 +80,7 @@ router.post('/install', jsonParser, async (request, response) => {
const { url, global } = request.body; const { url, global } = request.body;
if (global && !request.user.profile.admin) { 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.'); 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 }); 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); const { version, author, display_name } = await getManifest(extensionPath);
return response.send({ version, author, display_name, extensionPath }); return response.send({ version, author, display_name, extensionPath });
} catch (error) { } 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}`); 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; const { extensionName, global } = request.body;
if (global && !request.user.profile.admin) { 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.'); 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(); const currentBranch = await git.cwd(extensionPath).branch();
if (!isUpToDate) { if (!isUpToDate) {
await git.cwd(extensionPath).pull('origin', currentBranch.current); 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 { } 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'); await git.cwd(extensionPath).fetch('origin');
const fullCommitHash = await git.cwd(extensionPath).revparse(['HEAD']); 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 }); return response.send({ shortCommitHash, extensionPath, isUpToDate, remoteUrl });
} catch (error) { } 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}`); 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) { 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.'); 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.cpSync(sourcePath, destinationPath, { recursive: true, force: true });
fs.rmSync(sourcePath, { 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); return response.sendStatus(204);
} catch (error) { } 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.'); 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 // get only the working branch
const currentBranchName = currentBranch.current; const currentBranchName = currentBranch.current;
await git.cwd(extensionPath).fetch('origin'); await git.cwd(extensionPath).fetch('origin');
console.log(extensionName, currentBranchName, currentCommitHash); console.debug(extensionName, currentBranchName, currentCommitHash);
const { isUpToDate, remoteUrl } = await checkIfRepoIsUpToDate(extensionPath); const { isUpToDate, remoteUrl } = await checkIfRepoIsUpToDate(extensionPath);
return response.send({ currentBranchName, currentCommitHash, isUpToDate, remoteUrl }); return response.send({ currentBranchName, currentCommitHash, isUpToDate, remoteUrl });
} catch (error) { } 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}`); 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; const { extensionName, global } = request.body;
if (global && !request.user.profile.admin) { 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.'); 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 }); 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}`); return response.send(`Extension has been deleted at ${extensionPath}`);
} catch (error) { } 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}`); return response.status(500).send(`Server Error: ${error.message}`);
} }
}); });
@ -323,7 +323,7 @@ router.get('/discover', jsonParser, function (request, response) {
// Combine all extensions // Combine all extensions
const allExtensions = [...builtInExtensions, ...userExtensions, ...globalExtensions]; 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); return response.send(allExtensions);
}); });

View File

@ -21,7 +21,7 @@ router.post('/sanitize-filename', jsonParser, async (request, response) => {
const sanitizedFilename = sanitize(fileName); const sanitizedFilename = sanitize(fileName);
return response.send({ fileName: sanitizedFilename }); return response.send({ fileName: sanitizedFilename });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); 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); const pathToUpload = path.join(request.user.directories.files, request.body.name);
writeFileSyncAtomic(pathToUpload, request.body.data, 'base64'); writeFileSyncAtomic(pathToUpload, request.body.data, 'base64');
const url = clientRelativePath(request.user.directories.root, pathToUpload); 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 }); return response.send({ path: url });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -68,10 +68,10 @@ router.post('/delete', jsonParser, async (request, response) => {
} }
fs.rmSync(pathToDelete); 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); return response.sendStatus(200);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -87,7 +87,7 @@ router.post('/verify', jsonParser, async (request, response) => {
for (const url of request.body.urls) { for (const url of request.body.urls) {
const pathToVerify = path.join(request.user.directories.root, url); const pathToVerify = path.join(request.user.directories.root, url);
if (!pathToVerify.startsWith(request.user.directories.files)) { if (!pathToVerify.startsWith(request.user.directories.files)) {
console.debug(`File verification: Invalid path: ${pathToVerify}`); console.warn(`File verification: Invalid path: ${pathToVerify}`);
continue; continue;
} }
const fileExists = fs.existsSync(pathToVerify); const fileExists = fs.existsSync(pathToVerify);
@ -96,7 +96,7 @@ router.post('/verify', jsonParser, async (request, response) => {
return response.send(verified); return response.send(verified);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -34,7 +34,7 @@ router.post('/caption-image', jsonParser, async (request, response) => {
generationConfig: { maxOutputTokens: 1000 }, generationConfig: { maxOutputTokens: 1000 },
}; };
console.log('Multimodal captioning request', model, body); console.debug('Multimodal captioning request', model, body);
const result = await fetch(url, { const result = await fetch(url, {
body: JSON.stringify(body), body: JSON.stringify(body),
@ -46,13 +46,13 @@ router.post('/caption-image', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const error = await result.json(); 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 }); return response.status(result.status).send({ error: true });
} }
/** @type {any} */ /** @type {any} */
const data = await result.json(); const data = await result.json();
console.log('Multimodal captioning response', data); console.debug('Multimodal captioning response', data);
const candidates = data?.candidates; const candidates = data?.candidates;
if (!candidates) { if (!candidates) {

View File

@ -114,7 +114,7 @@ router.post('/delete', jsonParser, async (request, response) => {
if (group && Array.isArray(group.chats)) { if (group && Array.isArray(group.chats)) {
for (const chat of 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`); const pathToFile = path.join(request.user.directories.groupChats, `${id}.jsonl`);
if (fs.existsSync(pathToFile)) { if (fs.existsSync(pathToFile)) {

View File

@ -155,7 +155,7 @@ router.post('/cancel-task', jsonParser, async (request, response) => {
}); });
const data = await fetchResult.json(); const data = await fetchResult.json();
console.log(`Cancelled Horde task ${taskId}`); console.info(`Cancelled Horde task ${taskId}`);
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -174,7 +174,7 @@ router.post('/task-status', jsonParser, async (request, response) => {
}); });
const data = await fetchResult.json(); const data = await fetchResult.json();
console.log(`Horde task ${taskId} status:`, data); console.info(`Horde task ${taskId} status:`, data);
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.error(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 url = 'https://aihorde.net/api/v2/generate/text/async';
const agent = await getClientAgent(); const agent = await getClientAgent();
console.log(request.body); console.debug(request.body);
try { try {
const result = await fetch(url, { const result = await fetch(url, {
method: 'POST', method: 'POST',
@ -201,14 +201,14 @@ router.post('/generate-text', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const message = await result.text(); const message = await result.text();
console.log('Horde returned an error:', message); console.error('Horde returned an error:', message);
return response.send({ error: { message } }); return response.send({ error: { message } });
} }
const data = await result.json(); const data = await result.json();
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ error: true }); 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++) { for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
await delay(CHECK_INTERVAL); await delay(CHECK_INTERVAL);
const status = await ai_horde.getInterrogationStatus(result.id); const status = await ai_horde.getInterrogationStatus(result.id);
console.log(status); console.info(status);
if (status.state === HordeAsyncRequestStates.done) { if (status.state === HordeAsyncRequestStates.done) {
@ -263,7 +263,7 @@ router.post('/caption-image', jsonParser, async (request, response) => {
return response.sendStatus(500); return response.sendStatus(500);
} }
console.log('Image interrogation result:', status); console.debug('Image interrogation result:', status);
const caption = status?.forms[0]?.result?.caption || ''; const caption = status?.forms[0]?.result?.caption || '';
if (!caption) { if (!caption) {
@ -275,7 +275,7 @@ router.post('/caption-image', jsonParser, async (request, response) => {
} }
if (status.state === HordeAsyncRequestStates.faulted || status.state === HordeAsyncRequestStates.cancelled) { 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); return response.sendStatus(503);
} }
} }
@ -315,7 +315,7 @@ router.post('/generate-image', jsonParser, async (request, response) => {
try { try {
const maxLength = PROMPT_THRESHOLD - String(request.body.negative_prompt).length - 5; const maxLength = PROMPT_THRESHOLD - String(request.body.negative_prompt).length - 5;
if (String(request.body.prompt).length > maxLength) { 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); 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); const sanitized = sanitizeHordeImagePrompt(request.body.prompt);
if (request.body.prompt !== sanitized) { if (request.body.prompt !== sanitized) {
console.log('Stable Horde prompt was sanitized.'); console.info('Stable Horde prompt was sanitized.');
} }
request.body.prompt = sanitized; request.body.prompt = sanitized;
} }
const api_key_horde = readSecret(request.user.directories, SECRET_KEYS.HORDE) || ANONYMOUS_KEY; 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(); const ai_horde = await getHordeClient();
// noinspection JSCheckFunctionSignatures -- see @ts-ignore - use_gfpgan // noinspection JSCheckFunctionSignatures -- see @ts-ignore - use_gfpgan
@ -364,12 +364,12 @@ router.post('/generate-image', jsonParser, async (request, response) => {
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('Horde image generation request:', generation); console.debug('Horde image generation request:', generation);
const controller = new AbortController(); const controller = new AbortController();
request.socket.removeAllListeners('close'); request.socket.removeAllListeners('close');
request.socket.on('close', function () { request.socket.on('close', function () {
console.log('Horde image generation request aborted.'); console.info('Horde image generation request aborted.');
controller.abort(); controller.abort();
if (generation.id) ai_horde.deleteImageGenerationRequest(generation.id); if (generation.id) ai_horde.deleteImageGenerationRequest(generation.id);
}); });
@ -378,7 +378,7 @@ router.post('/generate-image', jsonParser, async (request, response) => {
controller.signal.throwIfAborted(); controller.signal.throwIfAborted();
await delay(CHECK_INTERVAL); await delay(CHECK_INTERVAL);
const check = await ai_horde.getImageGenerationCheck(generation.id); const check = await ai_horde.getImageGenerationCheck(generation.id);
console.log(check); console.info(check);
if (check.done) { if (check.done) {
const result = await ai_horde.getImageGenerationStatus(generation.id); const result = await ai_horde.getImageGenerationStatus(generation.id);

View File

@ -71,7 +71,7 @@ router.post('/upload', jsonParser, async (request, response) => {
await fs.promises.writeFile(pathToNewFile, new Uint8Array(imageBuffer)); await fs.promises.writeFile(pathToNewFile, new Uint8Array(imageBuffer));
response.send({ path: clientRelativePath(request.user.directories.root, pathToNewFile) }); response.send({ path: clientRelativePath(request.user.directories.root, pathToNewFile) });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
response.status(500).send({ error: 'Failed to save the image' }); response.status(500).send({ error: 'Failed to save the image' });
} }
}); });

View File

@ -120,7 +120,7 @@ router.post('/status', jsonParser, async function (req, res) {
const api_key_novel = readSecret(req.user.directories, SECRET_KEYS.NOVEL); const api_key_novel = readSecret(req.user.directories, SECRET_KEYS.NOVEL);
if (!api_key_novel) { if (!api_key_novel) {
console.log('NovelAI Access Token is missing.'); console.error('NovelAI Access Token is missing.');
return res.sendStatus(400); return res.sendStatus(400);
} }
@ -137,15 +137,15 @@ router.post('/status', jsonParser, async function (req, res) {
const data = await response.json(); const data = await response.json();
return res.send(data); return res.send(data);
} else if (response.status == 401) { } else if (response.status == 401) {
console.log('NovelAI Access Token is incorrect.'); console.error('NovelAI Access Token is incorrect.');
return res.send({ error: true }); return res.send({ error: true });
} }
else { else {
console.log('NovelAI returned an error:', response.statusText); console.error('NovelAI returned an error:', response.statusText);
return res.send({ error: true }); return res.send({ error: true });
} }
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return res.send({ error: true }); 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); const api_key_novel = readSecret(req.user.directories, SECRET_KEYS.NOVEL);
if (!api_key_novel) { if (!api_key_novel) {
console.log('NovelAI Access Token is missing.'); console.error('NovelAI Access Token is missing.');
return res.sendStatus(400); 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 = { const args = {
body: JSON.stringify(data), body: JSON.stringify(data),
@ -261,7 +261,7 @@ router.post('/generate', jsonParser, async function (req, res) {
if (!response.ok) { if (!response.ok) {
const text = await response.text(); const text = await response.text();
let message = 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 { try {
const data = JSON.parse(text); const data = JSON.parse(text);
@ -276,7 +276,7 @@ router.post('/generate', jsonParser, async function (req, res) {
/** @type {any} */ /** @type {any} */
const data = await response.json(); const data = await response.json();
console.log('NovelAI Output', data?.output); console.debug('NovelAI Output', data?.output);
return res.send(data); return res.send(data);
} }
} catch (error) { } catch (error) {
@ -292,12 +292,12 @@ router.post('/generate-image', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.NOVEL); const key = readSecret(request.user.directories, SECRET_KEYS.NOVEL);
if (!key) { if (!key) {
console.log('NovelAI Access Token is missing.'); console.error('NovelAI Access Token is missing.');
return response.sendStatus(400); return response.sendStatus(400);
} }
try { try {
console.log('NAI Diffusion request:', request.body); console.debug('NAI Diffusion request:', request.body);
const generateUrl = `${IMAGE_NOVELAI}/ai/generate-image`; const generateUrl = `${IMAGE_NOVELAI}/ai/generate-image`;
const generateResult = await fetch(generateUrl, { const generateResult = await fetch(generateUrl, {
method: 'POST', method: 'POST',
@ -358,7 +358,7 @@ router.post('/generate-image', jsonParser, async (request, response) => {
if (!generateResult.ok) { if (!generateResult.ok) {
const text = await generateResult.text(); 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); return response.sendStatus(500);
} }
@ -366,7 +366,7 @@ router.post('/generate-image', jsonParser, async (request, response) => {
const imageBuffer = await extractFileFromZipBuffer(archiveBuffer, '.png'); const imageBuffer = await extractFileFromZipBuffer(archiveBuffer, '.png');
if (!imageBuffer) { 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); return response.sendStatus(500);
} }
@ -378,7 +378,7 @@ router.post('/generate-image', jsonParser, async (request, response) => {
} }
try { try {
console.debug('Upscaling image...'); console.info('Upscaling image...');
const upscaleUrl = `${API_NOVELAI}/ai/upscale`; const upscaleUrl = `${API_NOVELAI}/ai/upscale`;
const upscaleResult = await fetch(upscaleUrl, { const upscaleResult = await fetch(upscaleUrl, {
method: 'POST', method: 'POST',
@ -413,7 +413,7 @@ router.post('/generate-image', jsonParser, async (request, response) => {
return response.send(originalBase64); return response.send(originalBase64);
} }
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); 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); const token = readSecret(request.user.directories, SECRET_KEYS.NOVEL);
if (!token) { if (!token) {
console.log('NovelAI Access Token is missing.'); console.error('NovelAI Access Token is missing.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -445,7 +445,7 @@ router.post('/generate-voice', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const errorText = await result.text(); 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); return response.sendStatus(500);
} }

View File

@ -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) { 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); return response.sendStatus(400);
} }
@ -93,7 +93,7 @@ router.post('/caption-image', jsonParser, async (request, response) => {
excludeKeysByYaml(body, request.body.custom_exclude_body); excludeKeysByYaml(body, request.body.custom_exclude_body);
} }
console.log('Multimodal captioning request', body); console.error('Multimodal captioning request', body);
let apiUrl = ''; let apiUrl = '';
@ -158,13 +158,13 @@ router.post('/caption-image', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); return response.status(500).send(text);
} }
/** @type {any} */ /** @type {any} */
const data = await result.json(); const data = await result.json();
console.log('Multimodal captioning response', data); console.debug('Multimodal captioning response', data);
const caption = data?.choices[0]?.message?.content; const caption = data?.choices[0]?.message?.content;
if (!caption) { if (!caption) {
@ -184,17 +184,17 @@ router.post('/transcribe-audio', urlencodedParser, async (request, response) =>
const key = readSecret(request.user.directories, SECRET_KEYS.OPENAI); const key = readSecret(request.user.directories, SECRET_KEYS.OPENAI);
if (!key) { if (!key) {
console.log('No OpenAI key found'); console.error('No OpenAI key found');
return response.sendStatus(400); return response.sendStatus(400);
} }
if (!request.file) { if (!request.file) {
console.log('No audio file found'); console.error('No audio file found');
return response.sendStatus(400); return response.sendStatus(400);
} }
const formData = new FormData(); 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('file', fs.createReadStream(request.file.path), { filename: 'audio.wav', contentType: 'audio/wav' });
formData.append('model', request.body.model); formData.append('model', request.body.model);
@ -213,13 +213,13 @@ router.post('/transcribe-audio', urlencodedParser, async (request, response) =>
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); return response.status(500).send(text);
} }
fs.rmSync(request.file.path); fs.rmSync(request.file.path);
const data = await result.json(); const data = await result.json();
console.log('OpenAI transcription response', data); console.debug('OpenAI transcription response', data);
return response.json(data); return response.json(data);
} catch (error) { } catch (error) {
console.error('OpenAI transcription failed', 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); const key = readSecret(request.user.directories, SECRET_KEYS.OPENAI);
if (!key) { if (!key) {
console.log('No OpenAI key found'); console.error('No OpenAI key found');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -253,7 +253,7 @@ router.post('/generate-voice', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); 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); const key = readSecret(request.user.directories, SECRET_KEYS.OPENAI);
if (!key) { if (!key) {
console.log('No OpenAI key found'); console.error('No OpenAI key found');
return response.sendStatus(400); 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', { const result = await fetch('https://api.openai.com/v1/images/generations', {
method: 'POST', method: 'POST',
@ -288,7 +288,7 @@ router.post('/generate-image', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); 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; const { input, provider_endpoint, response_format, voice, speed, model } = request.body;
if (!provider_endpoint) { 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); return response.sendStatus(400);
} }
@ -329,7 +329,7 @@ custom.post('/generate-voice', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); return response.status(500).send(text);
} }

View File

@ -96,7 +96,7 @@ router.post('/restore', jsonParser, function (request, response) {
return response.send(result); return response.send(result);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -94,25 +94,25 @@ router.post('/serpapi', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.SERPAPI); const key = readSecret(request.user.directories, SECRET_KEYS.SERPAPI);
if (!key) { if (!key) {
console.log('No SerpApi key found'); console.error('No SerpApi key found');
return response.sendStatus(400); return response.sendStatus(400);
} }
const { query } = request.body; const { query } = request.body;
const result = await fetch(`https://serpapi.com/search.json?q=${encodeURIComponent(query)}&api_key=${key}`); 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) { if (!result.ok) {
const text = await result.text(); 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); return response.status(500).send(text);
} }
const data = await result.json(); const data = await result.json();
return response.json(data); return response.json(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -128,7 +128,7 @@ router.post('/transcript', jsonParser, async (request, response) => {
const json = request.body.json; const json = request.body.json;
if (!id) { if (!id) {
console.log('Id is required for /transcript'); console.error('Id is required for /transcript');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -153,7 +153,7 @@ router.post('/transcript', jsonParser, async (request, response) => {
throw error; throw error;
} }
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -163,17 +163,17 @@ router.post('/searxng', jsonParser, async (request, response) => {
const { baseUrl, query, preferences } = request.body; const { baseUrl, query, preferences } = request.body;
if (!baseUrl || !query) { if (!baseUrl || !query) {
console.log('Missing required parameters for /searxng'); console.error('Missing required parameters for /searxng');
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('SearXNG query', baseUrl, query); console.debug('SearXNG query', baseUrl, query);
const mainPageUrl = new URL(baseUrl); const mainPageUrl = new URL(baseUrl);
const mainPageRequest = await fetch(mainPageUrl, { headers: visitHeaders }); const mainPageRequest = await fetch(mainPageUrl, { headers: visitHeaders });
if (!mainPageRequest.ok) { if (!mainPageRequest.ok) {
console.log('SearXNG request failed', mainPageRequest.statusText); console.error('SearXNG request failed', mainPageRequest.statusText);
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -197,14 +197,14 @@ router.post('/searxng', jsonParser, async (request, response) => {
if (!searchResult.ok) { if (!searchResult.ok) {
const text = await searchResult.text(); 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); return response.sendStatus(500);
} }
const data = await searchResult.text(); const data = await searchResult.text();
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.log('SearXNG request failed', error); console.error('SearXNG request failed', error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -214,7 +214,7 @@ router.post('/tavily', jsonParser, async (request, response) => {
const apiKey = readSecret(request.user.directories, SECRET_KEYS.TAVILY); const apiKey = readSecret(request.user.directories, SECRET_KEYS.TAVILY);
if (!apiKey) { if (!apiKey) {
console.log('No Tavily key found'); console.error('No Tavily key found');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -241,18 +241,18 @@ router.post('/tavily', jsonParser, async (request, response) => {
body: JSON.stringify(body), body: JSON.stringify(body),
}); });
console.log('Tavily query', query); console.debug('Tavily query', query);
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); return response.status(500).send(text);
} }
const data = await result.json(); const data = await result.json();
return response.json(data); return response.json(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -262,7 +262,7 @@ router.post('/visit', jsonParser, async (request, response) => {
const url = request.body.url; const url = request.body.url;
if (!url) { if (!url) {
console.log('No url provided for /visit'); console.error('No url provided for /visit');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -289,29 +289,29 @@ router.post('/visit', jsonParser, async (request, response) => {
throw new Error('Invalid hostname'); throw new Error('Invalid hostname');
} }
} catch (error) { } catch (error) {
console.log('Invalid url provided for /visit', url); console.error('Invalid url provided for /visit', url);
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('Visiting web URL', url); console.info('Visiting web URL', url);
const result = await fetch(url, { headers: visitHeaders }); const result = await fetch(url, { headers: visitHeaders });
if (!result.ok) { if (!result.ok) {
console.log(`Visit failed ${result.status} ${result.statusText}`); console.error(`Visit failed ${result.status} ${result.statusText}`);
return response.sendStatus(500); return response.sendStatus(500);
} }
const contentType = String(result.headers.get('content-type')); const contentType = String(result.headers.get('content-type'));
if (!contentType.includes('text/html')) { 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); return response.sendStatus(500);
} }
const text = await result.text(); const text = await result.text();
return response.send(text); return response.send(text);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -151,7 +151,7 @@ export function getAllSecrets(directories) {
const filePath = path.join(directories.root, SECRETS_FILE); const filePath = path.join(directories.root, SECRETS_FILE);
if (!fs.existsSync(filePath)) { if (!fs.existsSync(filePath)) {
console.log('Secrets file does not exist'); console.error('Secrets file does not exist');
return undefined; return undefined;
} }

View File

@ -104,7 +104,7 @@ function readPresetsFromDirectory(directoryPath, options = {}) {
fileNames.push(removeFileExtension ? item.replace(/\.[^/.]+$/, '') : item); fileNames.push(removeFileExtension ? item.replace(/\.[^/.]+$/, '') : item);
} catch { } catch {
// skip // 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); backupUserSettings(handle, true);
} }
} catch (err) { } 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); triggerAutoSave(request.user.profile.handle);
response.send({ result: 'ok' }); response.send({ result: 'ok' });
} catch (err) { } catch (err) {
console.log(err); console.error(err);
response.send(err); response.send(err);
} }
}); });
@ -291,7 +291,7 @@ router.post('/get-snapshots', jsonParser, async (request, response) => {
response.json(result); response.json(result);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
response.sendStatus(500); response.sendStatus(500);
} }
}); });
@ -315,7 +315,7 @@ router.post('/load-snapshot', jsonParser, async (request, response) => {
response.send(content); response.send(content);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
response.sendStatus(500); response.sendStatus(500);
} }
}); });
@ -325,7 +325,7 @@ router.post('/make-snapshot', jsonParser, async (request, response) => {
backupUserSettings(request.user.profile.handle, false); backupUserSettings(request.user.profile.handle, false);
response.sendStatus(204); response.sendStatus(204);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
response.sendStatus(500); response.sendStatus(500);
} }
}); });
@ -351,7 +351,7 @@ router.post('/restore-snapshot', jsonParser, async (request, response) => {
response.sendStatus(204); response.sendStatus(204);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
response.sendStatus(500); response.sendStatus(500);
} }
}); });

View File

@ -43,8 +43,8 @@ router.post('/recognize', jsonParser, async (req, res) => {
const start = performance.now(); const start = performance.now();
const result = await pipe(wav, { language: lang || null, task: 'transcribe' }); const result = await pipe(wav, { language: lang || null, task: 'transcribe' });
const end = performance.now(); const end = performance.now();
console.log(`Execution duration: ${(end - start) / 1000} seconds`); console.debug(`Execution duration: ${(end - start) / 1000} seconds`);
console.log('Transcribed audio:', result.text); console.debug('Transcribed audio:', result.text);
return res.json({ text: result.text }); return res.json({ text: result.text });
} catch (error) { } catch (error) {
@ -64,7 +64,7 @@ router.post('/synthesize', jsonParser, async (req, res) => {
const start = performance.now(); const start = performance.now();
const result = await pipe(text, { speaker_embeddings: speaker_embeddings }); const result = await pipe(text, { speaker_embeddings: speaker_embeddings });
const end = performance.now(); 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(); const wav = new wavefile.WaveFile();
wav.fromScratch(1, result.sampling_rate, '32f', result.audio); wav.fromScratch(1, result.sampling_rate, '32f', result.audio);

View File

@ -82,14 +82,14 @@ export function importRisuSprites(directories, data) {
return; 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); const files = fs.readdirSync(spritesPath);
outer: for (const [label, fileBase64] of images) { outer: for (const [label, fileBase64] of images) {
// Remove existing sprite with the same label // Remove existing sprite with the same label
for (const file of files) { for (const file of files) {
if (path.parse(file).name === label) { 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; continue outer;
} }
} }
@ -133,7 +133,7 @@ router.get('/get', jsonParser, function (request, response) {
} }
} }
catch (err) { catch (err) {
console.log(err); console.error(err);
} }
return response.send(sprites); return response.send(sprites);
}); });

View File

@ -45,7 +45,7 @@ router.post('/ping', jsonParser, async (request, response) => {
return response.sendStatus(200); return response.sendStatus(200);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -99,7 +99,7 @@ router.post('/upscalers', jsonParser, async (request, response) => {
return response.send(upscalers); return response.send(upscalers);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -131,7 +131,7 @@ router.post('/vaes', jsonParser, async (request, response) => {
const names = data.map(x => x.model_name); const names = data.map(x => x.model_name);
return response.send(names); return response.send(names);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -158,7 +158,7 @@ router.post('/samplers', jsonParser, async (request, response) => {
return response.send(names); return response.send(names);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -184,7 +184,7 @@ router.post('/schedulers', jsonParser, async (request, response) => {
const names = data.map(x => x.name); const names = data.map(x => x.name);
return response.send(names); return response.send(names);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); 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 })); const models = data.map(x => ({ value: x.title, text: x.title }));
return response.send(models); return response.send(models);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -230,7 +230,7 @@ router.post('/get-model', jsonParser, async (request, response) => {
const data = await result.json(); const data = await result.json();
return response.send(data['sd_model_checkpoint']); return response.send(data['sd_model_checkpoint']);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -283,13 +283,13 @@ router.post('/set-model', jsonParser, async (request, response) => {
break; 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); await delay(CHECK_INTERVAL);
} }
return response.sendStatus(200); return response.sendStatus(200);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -309,7 +309,7 @@ router.post('/generate', jsonParser, async (request, response) => {
} }
} }
} catch (error) { } catch (error) {
console.log('SD WebUI failed to get options:', error); console.error('SD WebUI failed to get options:', error);
} }
const controller = new AbortController(); const controller = new AbortController();
@ -323,7 +323,7 @@ router.post('/generate', jsonParser, async (request, response) => {
controller.abort(); controller.abort();
}); });
console.log('SD WebUI request:', request.body); console.debug('SD WebUI request:', request.body);
const txt2imgUrl = new URL(request.body.url); const txt2imgUrl = new URL(request.body.url);
txt2imgUrl.pathname = '/sdapi/v1/txt2img'; txt2imgUrl.pathname = '/sdapi/v1/txt2img';
const result = await fetch(txt2imgUrl, { const result = await fetch(txt2imgUrl, {
@ -344,7 +344,7 @@ router.post('/generate', jsonParser, async (request, response) => {
const data = await result.json(); const data = await result.json();
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -377,7 +377,7 @@ router.post('/sd-next/upscalers', jsonParser, async (request, response) => {
return response.send(names); return response.send(names);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -395,7 +395,7 @@ comfy.post('/ping', jsonParser, async (request, response) => {
return response.sendStatus(200); return response.sendStatus(200);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -413,7 +413,7 @@ comfy.post('/samplers', jsonParser, async (request, response) => {
const data = await result.json(); const data = await result.json();
return response.send(data.KSampler.input.required.sampler_name[0]); return response.send(data.KSampler.input.required.sampler_name[0]);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -441,7 +441,7 @@ comfy.post('/models', jsonParser, async (request, response) => {
return response.send(models); return response.send(models);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -459,7 +459,7 @@ comfy.post('/schedulers', jsonParser, async (request, response) => {
const data = await result.json(); const data = await result.json();
return response.send(data.KSampler.input.required.scheduler[0]); return response.send(data.KSampler.input.required.scheduler[0]);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -477,7 +477,7 @@ comfy.post('/vaes', jsonParser, async (request, response) => {
const data = await result.json(); const data = await result.json();
return response.send(data.VAELoader.input.required.vae_name[0]); return response.send(data.VAELoader.input.required.vae_name[0]);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -487,7 +487,7 @@ comfy.post('/workflows', jsonParser, async (request, response) => {
const data = getComfyWorkflows(request.user.directories); const data = getComfyWorkflows(request.user.directories);
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -501,7 +501,7 @@ comfy.post('/workflow', jsonParser, async (request, response) => {
const data = fs.readFileSync(filePath, { encoding: 'utf-8' }); const data = fs.readFileSync(filePath, { encoding: 'utf-8' });
return response.send(JSON.stringify(data)); return response.send(JSON.stringify(data));
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -513,7 +513,7 @@ comfy.post('/save-workflow', jsonParser, async (request, response) => {
const data = getComfyWorkflows(request.user.directories); const data = getComfyWorkflows(request.user.directories);
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -526,7 +526,7 @@ comfy.post('/delete-workflow', jsonParser, async (request, response) => {
} }
return response.sendStatus(200); return response.sendStatus(200);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -591,7 +591,7 @@ comfy.post('/generate', jsonParser, async (request, response) => {
const imgBuffer = await imgResponse.arrayBuffer(); const imgBuffer = await imgResponse.arrayBuffer();
return response.send(Buffer.from(imgBuffer).toString('base64')); return response.send(Buffer.from(imgBuffer).toString('base64'));
} catch (error) { } catch (error) {
console.log('ComfyUI error:', error); console.error('ComfyUI error:', error);
response.status(500).send(error.message); response.status(500).send(error.message);
return response; return response;
} }
@ -604,7 +604,7 @@ together.post('/models', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.TOGETHERAI); const key = readSecret(request.user.directories, SECRET_KEYS.TOGETHERAI);
if (!key) { if (!key) {
console.log('TogetherAI key not found.'); console.error('TogetherAI key not found.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -616,14 +616,14 @@ together.post('/models', jsonParser, async (request, response) => {
}); });
if (!modelsResponse.ok) { if (!modelsResponse.ok) {
console.log('TogetherAI returned an error.'); console.error('TogetherAI returned an error.');
return response.sendStatus(500); return response.sendStatus(500);
} }
const data = await modelsResponse.json(); const data = await modelsResponse.json();
if (!Array.isArray(data)) { if (!Array.isArray(data)) {
console.log('TogetherAI returned invalid data.'); console.error('TogetherAI returned invalid data.');
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -633,7 +633,7 @@ together.post('/models', jsonParser, async (request, response) => {
return response.send(models); return response.send(models);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -643,11 +643,11 @@ together.post('/generate', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.TOGETHERAI); const key = readSecret(request.user.directories, SECRET_KEYS.TOGETHERAI);
if (!key) { if (!key) {
console.log('TogetherAI key not found.'); console.error('TogetherAI key not found.');
return response.sendStatus(400); 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', { const result = await fetch('https://api.together.xyz/v1/images/generations', {
method: 'POST', method: 'POST',
@ -669,13 +669,13 @@ together.post('/generate', jsonParser, async (request, response) => {
}); });
if (!result.ok) { 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); return response.sendStatus(500);
} }
/** @type {any} */ /** @type {any} */
const data = await result.json(); const data = await result.json();
console.log('TogetherAI response:', data); console.debug('TogetherAI response:', data);
const choice = data?.data?.[0]; const choice = data?.data?.[0];
let b64_json = choice.b64_json; 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 }); return response.send({ format: 'jpg', data: b64_json });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -709,7 +709,7 @@ drawthings.post('/ping', jsonParser, async (request, response) => {
return response.sendStatus(200); return response.sendStatus(200);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -728,7 +728,7 @@ drawthings.post('/get-model', jsonParser, async (request, response) => {
return response.send(data['model']); return response.send(data['model']);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -747,14 +747,14 @@ drawthings.post('/get-upscaler', jsonParser, async (request, response) => {
return response.send(data['upscaler']); return response.send(data['upscaler']);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
drawthings.post('/generate', jsonParser, async (request, response) => { drawthings.post('/generate', jsonParser, async (request, response) => {
try { try {
console.log('SD DrawThings API request:', request.body); console.debug('SD DrawThings API request:', request.body);
const url = new URL(request.body.url); const url = new URL(request.body.url);
url.pathname = '/sdapi/v1/txt2img'; url.pathname = '/sdapi/v1/txt2img';
@ -781,7 +781,7 @@ drawthings.post('/generate', jsonParser, async (request, response) => {
const data = await result.json(); const data = await result.json();
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -794,21 +794,21 @@ pollinations.post('/models', jsonParser, async (_request, response) => {
const result = await fetch(modelsUrl); const result = await fetch(modelsUrl);
if (!result.ok) { 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.'); throw new Error('Pollinations request failed.');
} }
const data = await result.json(); const data = await result.json();
if (!Array.isArray(data)) { if (!Array.isArray(data)) {
console.log('Pollinations returned invalid data.'); console.error('Pollinations returned invalid data.');
throw new Error('Pollinations request failed.'); throw new Error('Pollinations request failed.');
} }
const models = data.map(x => ({ value: x, text: x })); const models = data.map(x => ({ value: x, text: x }));
return response.send(models); return response.send(models);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -829,12 +829,12 @@ pollinations.post('/generate', jsonParser, async (request, response) => {
}); });
promptUrl.search = params.toString(); promptUrl.search = params.toString();
console.log('Pollinations request URL:', promptUrl.toString()); console.info('Pollinations request URL:', promptUrl.toString());
const result = await fetch(promptUrl); const result = await fetch(promptUrl);
if (!result.ok) { 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.'); throw new Error('Pollinations request failed.');
} }
@ -843,7 +843,7 @@ pollinations.post('/generate', jsonParser, async (request, response) => {
return response.send({ image: base64 }); return response.send({ image: base64 });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -855,13 +855,13 @@ stability.post('/generate', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.STABILITY); const key = readSecret(request.user.directories, SECRET_KEYS.STABILITY);
if (!key) { if (!key) {
console.log('Stability AI key not found.'); console.error('Stability AI key not found.');
return response.sendStatus(400); return response.sendStatus(400);
} }
const { payload, model } = request.body; const { payload, model } = request.body;
console.log('Stability AI request:', model, payload); console.debug('Stability AI request:', model, payload);
const formData = new FormData(); const formData = new FormData();
for (const [key, value] of Object.entries(payload)) { for (const [key, value] of Object.entries(payload)) {
@ -896,14 +896,14 @@ stability.post('/generate', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const text = await result.text(); 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); return response.sendStatus(500);
} }
const buffer = await result.arrayBuffer(); const buffer = await result.arrayBuffer();
return response.send(Buffer.from(buffer).toString('base64')); return response.send(Buffer.from(buffer).toString('base64'));
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -915,7 +915,7 @@ blockentropy.post('/models', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY);
if (!key) { if (!key) {
console.log('Block Entropy key not found.'); console.error('Block Entropy key not found.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -927,21 +927,21 @@ blockentropy.post('/models', jsonParser, async (request, response) => {
}); });
if (!modelsResponse.ok) { if (!modelsResponse.ok) {
console.log('Block Entropy returned an error.'); console.error('Block Entropy returned an error.');
return response.sendStatus(500); return response.sendStatus(500);
} }
const data = await modelsResponse.json(); const data = await modelsResponse.json();
if (!Array.isArray(data)) { if (!Array.isArray(data)) {
console.log('Block Entropy returned invalid data.'); console.error('Block Entropy returned invalid data.');
return response.sendStatus(500); return response.sendStatus(500);
} }
const models = data.map(x => ({ value: x.name, text: x.name })); const models = data.map(x => ({ value: x.name, text: x.name }));
return response.send(models); return response.send(models);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -951,11 +951,11 @@ blockentropy.post('/generate', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY);
if (!key) { if (!key) {
console.log('Block Entropy key not found.'); console.error('Block Entropy key not found.');
return response.sendStatus(400); 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', { const result = await fetch('https://api.blockentropy.ai/sdapi/v1/txt2img', {
method: 'POST', method: 'POST',
@ -976,16 +976,16 @@ blockentropy.post('/generate', jsonParser, async (request, response) => {
}); });
if (!result.ok) { if (!result.ok) {
console.log('Block Entropy returned an error.'); console.error('Block Entropy returned an error.');
return response.sendStatus(500); return response.sendStatus(500);
} }
const data = await result.json(); const data = await result.json();
console.log('Block Entropy response:', data); console.debug('Block Entropy response:', data);
return response.send(data); return response.send(data);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -998,11 +998,11 @@ huggingface.post('/generate', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.HUGGINGFACE); const key = readSecret(request.user.directories, SECRET_KEYS.HUGGINGFACE);
if (!key) { if (!key) {
console.log('Hugging Face key not found.'); console.error('Hugging Face key not found.');
return response.sendStatus(400); 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}`, { const result = await fetch(`https://api-inference.huggingface.co/models/${request.body.model}`, {
method: 'POST', method: 'POST',
@ -1016,7 +1016,7 @@ huggingface.post('/generate', jsonParser, async (request, response) => {
}); });
if (!result.ok) { if (!result.ok) {
console.log('Hugging Face returned an error.'); console.error('Hugging Face returned an error.');
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -1025,7 +1025,7 @@ huggingface.post('/generate', jsonParser, async (request, response) => {
image: Buffer.from(buffer).toString('base64'), image: Buffer.from(buffer).toString('base64'),
}); });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -1037,7 +1037,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.NANOGPT); const key = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);
if (!key) { if (!key) {
console.log('NanoGPT key not found.'); console.error('NanoGPT key not found.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -1050,7 +1050,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => {
}); });
if (!modelsResponse.ok) { if (!modelsResponse.ok) {
console.log('NanoGPT returned an error.'); console.error('NanoGPT returned an error.');
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -1059,7 +1059,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => {
const imageModels = data?.models?.image; const imageModels = data?.models?.image;
if (!imageModels || typeof imageModels !== 'object') { if (!imageModels || typeof imageModels !== 'object') {
console.log('NanoGPT returned invalid data.'); console.error('NanoGPT returned invalid data.');
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -1067,7 +1067,7 @@ nanogpt.post('/models', jsonParser, async (request, response) => {
return response.send(models); return response.send(models);
} }
catch (error) { catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -1077,11 +1077,11 @@ nanogpt.post('/generate', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.NANOGPT); const key = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);
if (!key) { if (!key) {
console.log('NanoGPT key not found.'); console.error('NanoGPT key not found.');
return response.sendStatus(400); 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', { const result = await fetch('https://nano-gpt.com/api/generate-image', {
method: 'POST', method: 'POST',
@ -1093,7 +1093,7 @@ nanogpt.post('/generate', jsonParser, async (request, response) => {
}); });
if (!result.ok) { if (!result.ok) {
console.log('NanoGPT returned an error.'); console.error('NanoGPT returned an error.');
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -1102,14 +1102,14 @@ nanogpt.post('/generate', jsonParser, async (request, response) => {
const image = data?.data?.[0]?.b64_json; const image = data?.data?.[0]?.b64_json;
if (!image) { if (!image) {
console.log('NanoGPT returned invalid data.'); console.error('NanoGPT returned invalid data.');
return response.sendStatus(500); return response.sendStatus(500);
} }
return response.send({ image }); return response.send({ image });
} }
catch (error) { catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -1121,7 +1121,7 @@ bfl.post('/generate', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.BFL); const key = readSecret(request.user.directories, SECRET_KEYS.BFL);
if (!key) { if (!key) {
console.log('BFL key not found.'); console.error('BFL key not found.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -1173,7 +1173,7 @@ bfl.post('/generate', jsonParser, async (request, response) => {
delete requestBody.guidance; 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}`, { const result = await fetch(`https://api.bfl.ml/v1/${request.body.model}`, {
method: 'POST', method: 'POST',
@ -1185,7 +1185,7 @@ bfl.post('/generate', jsonParser, async (request, response) => {
}); });
if (!result.ok) { if (!result.ok) {
console.log('BFL returned an error.'); console.error('BFL returned an error.');
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -1201,7 +1201,7 @@ bfl.post('/generate', jsonParser, async (request, response) => {
if (!statusResult.ok) { if (!statusResult.ok) {
const text = await statusResult.text(); const text = await statusResult.text();
console.log('BFL returned an error.', text); console.error('BFL returned an error.', text);
return response.sendStatus(500); 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 }); throw new Error('BFL failed to generate image.', { cause: statusData });
} }
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -148,7 +148,7 @@ async function collectAndCreateStats(chatsPath, charactersPath) {
* @param {string} charactersPath Path to the directory containing the character files. * @param {string} charactersPath Path to the directory containing the character files.
*/ */
export async function recreateStats(handle, chatsPath, charactersPath) { 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); const stats = await collectAndCreateStats(chatsPath, charactersPath);
STATS.set(handle, stats); STATS.set(handle, stats);
await saveStatsToFile(); await saveStatsToFile();
@ -200,7 +200,7 @@ async function saveStatsToFile() {
await writeFileAtomic(statsFilePath, JSON.stringify(charStats)); await writeFileAtomic(statsFilePath, JSON.stringify(charStats));
TIMESTAMPS.set(handle, Date.now()); TIMESTAMPS.set(handle, Date.now());
} catch (error) { } catch (error) {
console.log('Failed to save stats to file.', error); console.error('Failed to save stats to file.', error);
} }
} }
} }

View File

@ -89,7 +89,6 @@ async function generateThumbnail(directories, type, file) {
let thumbnailFolder = getThumbnailFolder(directories, type); let thumbnailFolder = getThumbnailFolder(directories, type);
let originalFolder = getOriginalFolder(directories, type); let originalFolder = getOriginalFolder(directories, type);
if (thumbnailFolder === undefined || originalFolder === undefined) throw new Error('Invalid thumbnail type'); if (thumbnailFolder === undefined || originalFolder === undefined) throw new Error('Invalid thumbnail type');
const pathToCachedFile = path.join(thumbnailFolder, file); const pathToCachedFile = path.join(thumbnailFolder, file);
const pathToOriginalFile = path.join(originalFolder, file); const pathToOriginalFile = path.join(originalFolder, file);
@ -104,7 +103,7 @@ async function generateThumbnail(directories, type, file) {
const cachedStat = fs.statSync(pathToCachedFile); const cachedStat = fs.statSync(pathToCachedFile);
if (originalStat.mtimeMs > cachedStat.ctimeMs) { if (originalStat.mtimeMs > cachedStat.ctimeMs) {
//console.log('Original file changed. Regenerating thumbnail...'); //console.warn('Original file changed. Regenerating thumbnail...');
shouldRegenerate = true; shouldRegenerate = true;
} }
} }
@ -157,7 +156,7 @@ export async function ensureThumbnailCache() {
return; return;
} }
console.log('Generating thumbnails cache. Please wait...'); console.info('Generating thumbnails cache. Please wait...');
const bgFiles = fs.readdirSync(directories.backgrounds); const bgFiles = fs.readdirSync(directories.backgrounds);
const tasks = []; const tasks = [];
@ -167,7 +166,7 @@ export async function ensureThumbnailCache() {
} }
await Promise.all(tasks); await Promise.all(tasks);
console.log(`Done! Generated: ${bgFiles.length} preview images`); console.info(`Done! Generated: ${bgFiles.length} preview images`);
} }
} }

View File

@ -96,7 +96,7 @@ async function getPathToTokenizer(model, fallbackModel) {
throw new Error('Downloading tokenizers is disabled, the model is not cached'); 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); const response = await fetch(model);
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to fetch the model: ${response.status} ${response.statusText}`); throw new Error(`Failed to fetch the model: ${response.status} ${response.statusText}`);
@ -108,7 +108,7 @@ async function getPathToTokenizer(model, fallbackModel) {
} catch (error) { } catch (error) {
const getLastSegment = str => str?.split('/')?.pop() || ''; const getLastSegment = str => str?.split('/')?.pop() || '';
if (fallbackModel) { 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; return fallbackModel;
} }
@ -156,7 +156,7 @@ class SentencePieceTokenizer {
const pathToModel = await getPathToTokenizer(this.#model, this.#fallbackModel); const pathToModel = await getPathToTokenizer(this.#model, this.#fallbackModel);
this.#instance = new SentencePieceProcessor(); this.#instance = new SentencePieceProcessor();
await this.#instance.load(pathToModel); 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; return this.#instance;
} catch (error) { } catch (error) {
console.error('Sentencepiece tokenizer failed to load: ' + this.#model, 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 pathToModel = await getPathToTokenizer(this.#model, this.#fallbackModel);
const arrayBuffer = fs.readFileSync(pathToModel).buffer; const arrayBuffer = fs.readFileSync(pathToModel).buffer;
this.#instance = await Tokenizer.fromJSON(arrayBuffer); 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; return this.#instance;
} catch (error) { } catch (error) {
console.error('Web tokenizer failed to load: ' + this.#model, 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); const tokenizer = tiktoken.encoding_for_model(model);
console.log('Instantiated the tokenizer for', model); console.info('Instantiated the tokenizer for', model);
tokenizersCache[model] = tokenizer; tokenizersCache[model] = tokenizer;
return tokenizer; return tokenizer;
} }
@ -489,7 +489,7 @@ function createSentencepieceEncodingHandler(tokenizer) {
const chunks = instance?.encodePieces(text); const chunks = instance?.encodePieces(text);
return response.send({ ids, count, chunks }); return response.send({ ids, count, chunks });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ ids: [], count: 0, chunks: [] }); return response.send({ ids: [], count: 0, chunks: [] });
} }
}; };
@ -520,7 +520,7 @@ function createSentencepieceDecodingHandler(tokenizer) {
const text = chunks.join(''); const text = chunks.join('');
return response.send({ text, chunks }); return response.send({ text, chunks });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ text: '', chunks: [] }); return response.send({ text: '', chunks: [] });
} }
}; };
@ -549,7 +549,7 @@ function createTiktokenEncodingHandler(modelId) {
const chunks = await getTiktokenChunks(tokenizer, tokens); const chunks = await getTiktokenChunks(tokenizer, tokens);
return response.send({ ids: tokens, count: tokens.length, chunks }); return response.send({ ids: tokens, count: tokens.length, chunks });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ ids: [], count: 0, chunks: [] }); return response.send({ ids: [], count: 0, chunks: [] });
} }
}; };
@ -578,7 +578,7 @@ function createTiktokenDecodingHandler(modelId) {
const text = new TextDecoder().decode(textBytes); const text = new TextDecoder().decode(textBytes);
return response.send({ text }); return response.send({ text });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ text: '' }); return response.send({ text: '' });
} }
}; };
@ -608,7 +608,7 @@ function createWebTokenizerEncodingHandler(tokenizer) {
const chunks = getWebTokenizersChunks(instance, tokens); const chunks = getWebTokenizersChunks(instance, tokens);
return response.send({ ids: tokens, count: tokens.length, chunks }); return response.send({ ids: tokens, count: tokens.length, chunks });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ ids: [], count: 0, chunks: [] }); return response.send({ ids: [], count: 0, chunks: [] });
} }
}; };
@ -639,7 +639,7 @@ function createWebTokenizerDecodingHandler(tokenizer) {
const text = instance.decode(new Int32Array(ids)); const text = instance.decode(new Int32Array(ids));
return response.send({ text, chunks }); return response.send({ text, chunks });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ text: '', chunks: [] }); return response.send({ text: '', chunks: [] });
} }
}; };
@ -739,7 +739,7 @@ router.post('/openai/encode', jsonParser, async function (req, res) {
const handler = createTiktokenEncodingHandler(model); const handler = createTiktokenEncodingHandler(model);
return handler(req, res); return handler(req, res);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return res.send({ ids: [], count: 0, chunks: [] }); return res.send({ ids: [], count: 0, chunks: [] });
} }
}); });
@ -807,7 +807,7 @@ router.post('/openai/decode', jsonParser, async function (req, res) {
const handler = createTiktokenDecodingHandler(model); const handler = createTiktokenDecodingHandler(model);
return handler(req, res); return handler(req, res);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return res.send({ text: '' }); return res.send({ text: '' });
} }
}); });
@ -946,7 +946,7 @@ router.post('/remote/kobold/count', jsonParser, async function (request, respons
const result = await fetch(url, args); const result = await fetch(url, args);
if (!result.ok) { 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 }); return response.send({ error: true });
} }
@ -955,7 +955,7 @@ router.post('/remote/kobold/count', jsonParser, async function (request, respons
const ids = data['ids'] ?? []; const ids = data['ids'] ?? [];
return response.send({ count, ids }); return response.send({ count, ids });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ error: true }); return response.send({ error: true });
} }
}); });
@ -1010,7 +1010,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re
const result = await fetch(url, args); const result = await fetch(url, args);
if (!result.ok) { 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 }); return response.send({ error: true });
} }
@ -1020,7 +1020,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re
return response.send({ count, ids }); return response.send({ count, ids });
} catch (error) { } catch (error) {
console.log(error); console.error(error);
return response.send({ error: true }); return response.send({ error: true });
} }
}); });

View File

@ -35,7 +35,7 @@ function decodeBuffer(buffer) {
try { try {
return iconv.decode(Buffer.from(buffer), 'utf-8'); return iconv.decode(Buffer.from(buffer), 'utf-8');
} catch (error) { } catch (error) {
console.log('Failed to decode buffer:', error); console.warn('Failed to decode buffer:', error);
return Buffer.from(buffer).toString('utf-8'); 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); const url = readSecret(request.user.directories, SECRET_KEYS.LIBRE_URL);
if (!url) { if (!url) {
console.log('LibreTranslate URL is not configured.'); console.error('LibreTranslate URL is not configured.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -69,7 +69,7 @@ router.post('/libre', jsonParser, async (request, response) => {
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('Input text: ' + text); console.debug('Input text: ' + text);
const result = await fetch(url, { const result = await fetch(url, {
method: 'POST', method: 'POST',
@ -85,17 +85,17 @@ router.post('/libre', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const error = await result.text(); const error = await result.text();
console.log('LibreTranslate error: ', result.statusText, error); console.error('LibreTranslate error: ', result.statusText, error);
return response.sendStatus(500); return response.sendStatus(500);
} }
/** @type {any} */ /** @type {any} */
const json = await result.json(); const json = await result.json();
console.log('Translated text: ' + json.translatedText); console.debug('Translated text: ' + json.translatedText);
return response.send(json.translatedText); return response.send(json.translatedText);
} catch (error) { } catch (error) {
console.log('Translation error: ' + error.message); console.error('Translation error: ' + error.message);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -109,14 +109,14 @@ router.post('/google', jsonParser, async (request, response) => {
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('Input text: ' + text); console.debug('Input text: ' + text);
const { generateRequestUrl, normaliseResponse } = getGoogleTranslateClient(); const { generateRequestUrl, normaliseResponse } = getGoogleTranslateClient();
const requestUrl = generateRequestUrl(text, { to: lang }); const requestUrl = generateRequestUrl(text, { to: lang });
const result = await fetch(requestUrl); const result = await fetch(requestUrl);
if (!result.ok) { if (!result.ok) {
console.log('Google Translate error: ', result.statusText); console.error('Google Translate error: ', result.statusText);
return response.sendStatus(500); return response.sendStatus(500);
} }
@ -125,10 +125,10 @@ router.post('/google', jsonParser, async (request, response) => {
const translatedText = translateResponse.text; const translatedText = translateResponse.text;
response.setHeader('Content-Type', 'text/plain; charset=utf-8'); response.setHeader('Content-Type', 'text/plain; charset=utf-8');
console.log('Translated text: ' + translatedText); console.debug('Translated text: ' + translatedText);
return response.send(translatedText); return response.send(translatedText);
} catch (error) { } catch (error) {
console.log('Translation error', error); console.error('Translation error', error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -161,7 +161,7 @@ router.post('/yandex', jsonParser, async (request, response) => {
params.append('lang', lang); params.append('lang', lang);
const ucid = uuidv4().replaceAll('-', ''); 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`, { const result = await fetch(`https://translate.yandex.net/api/v1/tr.json/translate?ucid=${ucid}&srv=android&format=text`, {
method: 'POST', method: 'POST',
@ -173,18 +173,18 @@ router.post('/yandex', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const error = await result.text(); const error = await result.text();
console.log('Yandex error: ', result.statusText, error); console.error('Yandex error: ', result.statusText, error);
return response.sendStatus(500); return response.sendStatus(500);
} }
/** @type {any} */ /** @type {any} */
const json = await result.json(); const json = await result.json();
const translated = json.text.join(); const translated = json.text.join();
console.log('Translated text: ' + translated); console.debug('Translated text: ' + translated);
return response.send(translated); return response.send(translated);
} catch (error) { } catch (error) {
console.log('Translation error: ' + error.message); console.error('Translation error: ' + error.message);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -195,7 +195,7 @@ router.post('/lingva', jsonParser, async (request, response) => {
const baseUrl = secretUrl || LINGVA_DEFAULT; const baseUrl = secretUrl || LINGVA_DEFAULT;
if (!secretUrl && baseUrl === 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') { 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); return response.sendStatus(400);
} }
console.log('Input text: ' + text); console.debug('Input text: ' + text);
const url = urlJoin(baseUrl, 'auto', lang, encodeURIComponent(text)); const url = urlJoin(baseUrl, 'auto', lang, encodeURIComponent(text));
const result = await fetch(url); const result = await fetch(url);
if (!result.ok) { if (!result.ok) {
const error = await result.text(); const error = await result.text();
console.log('Lingva error: ', result.statusText, error); console.error('Lingva error: ', result.statusText, error);
} }
/** @type {any} */ /** @type {any} */
const data = await result.json(); const data = await result.json();
console.log('Translated text: ' + data.translation); console.debug('Translated text: ' + data.translation);
return response.send(data.translation); return response.send(data.translation);
} catch (error) { } catch (error) {
console.log('Translation error', error); console.error('Translation error', error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -238,7 +238,7 @@ router.post('/deepl', jsonParser, async (request, response) => {
const key = readSecret(request.user.directories, SECRET_KEYS.DEEPL); const key = readSecret(request.user.directories, SECRET_KEYS.DEEPL);
if (!key) { if (!key) {
console.log('DeepL key is not configured.'); console.error('DeepL key is not configured.');
return response.sendStatus(400); return response.sendStatus(400);
} }
@ -254,7 +254,7 @@ router.post('/deepl', jsonParser, async (request, response) => {
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('Input text: ' + text); console.debug('Input text: ' + text);
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append('text', text); params.append('text', text);
@ -280,17 +280,17 @@ router.post('/deepl', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const error = await result.text(); const error = await result.text();
console.log('DeepL error: ', result.statusText, error); console.error('DeepL error: ', result.statusText, error);
return response.sendStatus(500); return response.sendStatus(500);
} }
/** @type {any} */ /** @type {any} */
const json = await result.json(); 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); return response.send(json.translations[0].text);
} catch (error) { } catch (error) {
console.log('Translation error: ' + error.message); console.error('Translation error: ' + error.message);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -376,7 +376,7 @@ router.post('/deeplx', jsonParser, async (request, response) => {
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('Input text: ' + text); console.debug('Input text: ' + text);
const result = await fetch(url, { const result = await fetch(url, {
method: 'POST', method: 'POST',
@ -393,17 +393,17 @@ router.post('/deeplx', jsonParser, async (request, response) => {
if (!result.ok) { if (!result.ok) {
const error = await result.text(); const error = await result.text();
console.log('DeepLX error: ', result.statusText, error); console.error('DeepLX error: ', result.statusText, error);
return response.sendStatus(500); return response.sendStatus(500);
} }
/** @type {any} */ /** @type {any} */
const json = await result.json(); const json = await result.json();
console.log('Translated text: ' + json.data); console.debug('Translated text: ' + json.data);
return response.send(json.data); return response.send(json.data);
} catch (error) { } catch (error) {
console.log('DeepLX translation error: ' + error.message); console.error('DeepLX translation error: ' + error.message);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });
@ -429,14 +429,14 @@ router.post('/bing', jsonParser, async (request, response) => {
return response.sendStatus(400); return response.sendStatus(400);
} }
console.log('Input text: ' + text); console.debug('Input text: ' + text);
const result = await bingTranslate(text, null, lang); const result = await bingTranslate(text, null, lang);
const translatedText = result?.translation; const translatedText = result?.translation;
console.log('Translated text: ' + translatedText); console.debug('Translated text: ' + translatedText);
return response.send(translatedText); return response.send(translatedText);
} catch (error) { } catch (error) {
console.log('Translation error', error); console.error('Translation error', error);
return response.sendStatus(500); return response.sendStatus(500);
} }
}); });

View File

@ -53,12 +53,12 @@ router.post('/get', requireAdminMiddleware, jsonParser, async (_request, respons
router.post('/disable', requireAdminMiddleware, jsonParser, async (request, response) => { router.post('/disable', requireAdminMiddleware, jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); return response.status(400).json({ error: 'Missing required fields' });
} }
if (request.body.handle === request.user.profile.handle) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); 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) => { router.post('/enable', requireAdminMiddleware, jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); 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) => { router.post('/promote', requireAdminMiddleware, jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); 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) => { router.post('/demote', requireAdminMiddleware, jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); return response.status(400).json({ error: 'Missing required fields' });
} }
if (request.body.handle === request.user.profile.handle) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); 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) => { router.post('/create', requireAdminMiddleware, jsonParser, async (request, response) => {
try { try {
if (!request.body.handle || !request.body.name) { 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' }); 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()); const handle = lodash.kebabCase(String(request.body.handle).toLowerCase().trim());
if (!handle) { if (!handle) {
console.log('Create user failed: Invalid handle'); console.error('Create user failed: Invalid handle');
return response.status(400).json({ error: 'Invalid handle' }); return response.status(400).json({ error: 'Invalid handle' });
} }
if (handles.some(x => x === 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' }); 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); await storage.setItem(toKey(handle), newUser);
// Create user directories // Create user directories
console.log('Creating data directories for', newUser.handle); console.info('Creating data directories for', newUser.handle);
await ensurePublicDirectoriesExist(); await ensurePublicDirectoriesExist();
const directories = getUserDirectories(newUser.handle); const directories = getUserDirectories(newUser.handle);
await checkForNewContent([directories]); await checkForNewContent([directories]);
@ -206,17 +206,17 @@ router.post('/create', requireAdminMiddleware, jsonParser, async (request, respo
router.post('/delete', requireAdminMiddleware, jsonParser, async (request, response) => { router.post('/delete', requireAdminMiddleware, jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); return response.status(400).json({ error: 'Missing required fields' });
} }
if (request.body.handle === request.user.profile.handle) { 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' }); return response.status(400).json({ error: 'Cannot delete yourself' });
} }
if (request.body.handle === DEFAULT_USER.handle) { 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.' }); 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) { if (request.body.purge) {
const directories = getUserDirectories(request.body.handle); 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 }); 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) => { router.post('/slugify', requireAdminMiddleware, jsonParser, async (request, response) => {
try { try {
if (!request.body.text) { 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' }); return response.status(400).json({ error: 'Missing required fields' });
} }

View File

@ -57,18 +57,18 @@ router.get('/me', async (request, response) => {
router.post('/change-avatar', jsonParser, async (request, response) => { router.post('/change-avatar', jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); return response.status(400).json({ error: 'Missing required fields' });
} }
if (request.body.handle !== request.user.profile.handle && !request.user.profile.admin) { 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' }); return response.status(403).json({ error: 'Unauthorized' });
} }
// Avatar is not a data URL or not an empty string // Avatar is not a data URL or not an empty string
if (!request.body.avatar.startsWith('data:image/') && request.body.avatar !== '') { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); 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) => { router.post('/change-password', jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); return response.status(400).json({ error: 'Missing required fields' });
} }
if (request.body.handle !== request.user.profile.handle && !request.user.profile.admin) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); return response.status(404).json({ error: 'User not found' });
} }
if (!user.enabled) { 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' }); return response.status(403).json({ error: 'User is disabled' });
} }
if (!request.user.profile.admin && user.password && user.password !== getPasswordHash(request.body.oldPassword, user.salt)) { 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' }); return response.status(403).json({ error: 'Incorrect password' });
} }
@ -141,12 +141,12 @@ router.post('/backup', jsonParser, async (request, response) => {
const handle = request.body.handle; const handle = request.body.handle;
if (!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' }); return response.status(400).json({ error: 'Missing required fields' });
} }
if (handle !== request.user.profile.handle && !request.user.profile.admin) { 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' }); return response.status(403).json({ error: 'Unauthorized' });
} }
@ -162,7 +162,7 @@ router.post('/reset-settings', jsonParser, async (request, response) => {
const password = request.body.password; const password = request.body.password;
if (request.user.profile.password && request.user.profile.password !== getPasswordHash(password, request.user.profile.salt)) { 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' }); 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) => { router.post('/change-name', jsonParser, async (request, response) => {
try { try {
if (!request.body.name || !request.body.handle) { 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' }); return response.status(400).json({ error: 'Missing required fields' });
} }
if (request.body.handle !== request.user.profile.handle && !request.user.profile.admin) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); 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) => { router.post('/reset-step1', jsonParser, async (request, response) => {
try { try {
const resetCode = String(crypto.randomInt(1000, 9999)); const resetCode = String(crypto.randomInt(1000, 9999));
console.log(); console.info();
console.log(color.magenta(`${request.user.profile.name}, your account reset code is: `) + color.red(resetCode)); console.info(color.magenta(`${request.user.profile.name}, your account reset code is: `) + color.red(resetCode));
console.log(); console.info();
RESET_CACHE.set(request.user.profile.handle, resetCode); RESET_CACHE.set(request.user.profile.handle, resetCode);
return response.sendStatus(204); return response.sendStatus(204);
} catch (error) { } catch (error) {
@ -224,23 +224,23 @@ router.post('/reset-step1', jsonParser, async (request, response) => {
router.post('/reset-step2', jsonParser, async (request, response) => { router.post('/reset-step2', jsonParser, async (request, response) => {
try { try {
if (!request.body.code) { 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' }); 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)) { 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' }); return response.status(400).json({ error: 'Incorrect password' });
} }
const code = RESET_CACHE.get(request.user.profile.handle); const code = RESET_CACHE.get(request.user.profile.handle);
if (!code || code !== request.body.code) { 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' }); 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 fsPromises.rm(request.user.directories.root, { recursive: true, force: true });
await ensurePublicDirectoriesExist(); await ensurePublicDirectoriesExist();

View File

@ -56,7 +56,7 @@ router.post('/list', async (_request, response) => {
router.post('/login', jsonParser, async (request, response) => { router.post('/login', jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); return response.status(403).json({ error: 'Incorrect credentials' });
} }
if (!user.enabled) { 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' }); return response.status(403).json({ error: 'User is disabled' });
} }
if (user.password && user.password !== getPasswordHash(request.body.password, user.salt)) { 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' }); return response.status(403).json({ error: 'Incorrect credentials' });
} }
@ -88,11 +88,11 @@ router.post('/login', jsonParser, async (request, response) => {
await loginLimiter.delete(ip); await loginLimiter.delete(ip);
request.session.handle = user.handle; 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 }); return response.json({ handle: user.handle });
} catch (error) { } catch (error) {
if (error instanceof RateLimiterRes) { 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.' }); 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) => { router.post('/recover-step1', jsonParser, async (request, response) => {
try { try {
if (!request.body.handle) { 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' }); 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)); const user = await storage.getItem(toKey(request.body.handle));
if (!user) { 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' }); return response.status(404).json({ error: 'User not found' });
} }
if (!user.enabled) { 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' }); return response.status(403).json({ error: 'User is disabled' });
} }
const mfaCode = String(crypto.randomInt(1000, 9999)); const mfaCode = String(crypto.randomInt(1000, 9999));
console.log(); console.info();
console.log(color.blue(`${user.name}, your password recovery code is: `) + color.magenta(mfaCode)); console.info(color.blue(`${user.name}, your password recovery code is: `) + color.magenta(mfaCode));
console.log(); console.info();
MFA_CACHE.set(user.handle, mfaCode); MFA_CACHE.set(user.handle, mfaCode);
return response.sendStatus(204); return response.sendStatus(204);
} catch (error) { } catch (error) {
if (error instanceof RateLimiterRes) { 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.' }); 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) => { router.post('/recover-step2', jsonParser, async (request, response) => {
try { try {
if (!request.body.handle || !request.body.code) { 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' }); 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); const ip = getIpFromRequest(request);
if (!user) { 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' }); return response.status(404).json({ error: 'User not found' });
} }
if (!user.enabled) { 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' }); 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) { if (request.body.code !== mfaCode) {
await recoverLimiter.consume(ip); 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' }); return response.status(403).json({ error: 'Incorrect code' });
} }
@ -186,7 +186,7 @@ router.post('/recover-step2', jsonParser, async (request, response) => {
return response.sendStatus(204); return response.sendStatus(204);
} catch (error) { } catch (error) {
if (error instanceof RateLimiterRes) { 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.' }); return response.status(429).send({ error: 'Too many attempts. Try again later or contact your admin.' });
} }

View File

@ -360,7 +360,7 @@ async function regenerateCorruptedIndexErrorHandler(req, res, error) {
if (exists) { if (exists) {
const path = index.folderPath; const path = index.folderPath;
console.error(`Corrupted index detected at ${path}, regenerating...`); console.warn(`Corrupted index detected at ${path}, regenerating...`);
await index.deleteIndex(); await index.deleteIndex();
return res.redirect(307, req.originalUrl + '?regenerated=true'); return res.redirect(307, req.originalUrl + '?regenerated=true');
} }
@ -474,7 +474,7 @@ router.post('/purge-all', jsonParser, async (req, res) => {
continue; continue;
} }
await fs.promises.rm(sourcePath, { recursive: true }); 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); return res.sendStatus(200);
@ -498,7 +498,7 @@ router.post('/purge', jsonParser, async (req, res) => {
continue; continue;
} }
await fs.promises.rm(sourcePath, { recursive: true }); 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); return res.sendStatus(200);

View File

@ -25,7 +25,7 @@ export function readWorldInfoFile(directories, worldInfoName, allowDummy) {
const pathToWorldInfo = path.join(directories.worlds, filename); const pathToWorldInfo = path.join(directories.worlds, filename);
if (!fs.existsSync(pathToWorldInfo)) { if (!fs.existsSync(pathToWorldInfo)) {
console.log(`World info file ${filename} doesn't exist.`); console.error(`World info file ${filename} doesn't exist.`);
return dummyObject; return dummyObject;
} }

View File

@ -43,9 +43,9 @@ export default function initRequestProxy({ enabled, url, bypass }) {
http.globalAgent = proxyAgent; http.globalAgent = proxyAgent;
https.globalAgent = proxyAgent; https.globalAgent = proxyAgent;
console.log(); console.info();
console.log(color.green(LOG_HEADER), 'Proxy URL is used:', color.blue(url)); console.info(color.green(LOG_HEADER), 'Proxy URL is used:', color.blue(url));
console.log(); console.info();
} catch (error) { } catch (error) {
console.error(color.red(LOG_HEADER), 'Failed to initialize request proxy:', error); console.error(color.red(LOG_HEADER), 'Failed to initialize request proxy:', error);
} }

View File

@ -13,6 +13,7 @@ import _ from 'lodash';
import yauzl from 'yauzl'; import yauzl from 'yauzl';
import mime from 'mime-types'; import mime from 'mime-types';
import { default as simpleGit } from 'simple-git'; import { default as simpleGit } from 'simple-git';
import { LOG_LEVELS } from './constants.js';
/** /**
* Parsed config object. * Parsed config object.
@ -149,6 +150,7 @@ export function getHexString(length) {
*/ */
export function formatBytes(bytes) { export function formatBytes(bytes) {
if (bytes === 0) return '0 B'; if (bytes === 0) return '0 B';
const k = 1024; const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB']; const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k)); const i = Math.floor(Math.log(bytes) / Math.log(k));
@ -285,10 +287,11 @@ export function deepMerge(target, source) {
if (isObject(target) && isObject(source)) { if (isObject(target) && isObject(source)) {
Object.keys(source).forEach(key => { Object.keys(source).forEach(key => {
if (isObject(source[key])) { if (isObject(source[key])) {
if (!(key in target)) if (!(key in target)) {
Object.assign(output, { [key]: source[key] }); Object.assign(output, { [key]: source[key] });
else } else {
output[key] = deepMerge(target[key], source[key]); output[key] = deepMerge(target[key], source[key]);
}
} else { } else {
Object.assign(output, { [key]: source[key] }); Object.assign(output, { [key]: source[key] });
} }
@ -466,7 +469,9 @@ export function forwardFetchResponse(from, to) {
from.body.pipe(to); from.body.pipe(to);
to.socket.on('close', function () { 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 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. * MemoryLimitedMap class that limits the memory usage of string values.
*/ */