mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	Merge branch 'staging' into novelai-router
This commit is contained in:
		| @@ -58,6 +58,7 @@ module.exports = { | |||||||
|         'comma-dangle': ['error', 'always-multiline'], |         'comma-dangle': ['error', 'always-multiline'], | ||||||
|         'eol-last': ['error', 'always'], |         'eol-last': ['error', 'always'], | ||||||
|         'no-trailing-spaces': 'error', |         'no-trailing-spaces': 'error', | ||||||
|  |         'object-curly-spacing': ['error', 'always'], | ||||||
|  |  | ||||||
|         // These rules should eventually be enabled. |         // These rules should eventually be enabled. | ||||||
|         'no-async-promise-executor': 'off', |         'no-async-promise-executor': 'off', | ||||||
|   | |||||||
| @@ -2914,7 +2914,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, | |||||||
|         let textareaText; |         let textareaText; | ||||||
|         if (type !== 'regenerate' && type !== 'swipe' && type !== 'quiet' && !isImpersonate && !dryRun) { |         if (type !== 'regenerate' && type !== 'swipe' && type !== 'quiet' && !isImpersonate && !dryRun) { | ||||||
|             is_send_press = true; |             is_send_press = true; | ||||||
|             textareaText = $('#send_textarea').val(); |             textareaText = String($('#send_textarea').val()); | ||||||
|             $('#send_textarea').val('').trigger('input'); |             $('#send_textarea').val('').trigger('input'); | ||||||
|         } else { |         } else { | ||||||
|             textareaText = ''; |             textareaText = ''; | ||||||
| @@ -2960,7 +2960,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, | |||||||
|         //********************************* |         //********************************* | ||||||
|  |  | ||||||
|         //for normal messages sent from user.. |         //for normal messages sent from user.. | ||||||
|         if ((textareaText != '' || hasPendingFileAttachment()) && !automatic_trigger && type !== 'quiet') { |         if ((textareaText != '' || hasPendingFileAttachment()) && !automatic_trigger && type !== 'quiet' && !dryRun) { | ||||||
|             // If user message contains no text other than bias - send as a system message |             // If user message contains no text other than bias - send as a system message | ||||||
|             if (messageBias && replaceBiasMarkup(textareaText).trim().length === 0) { |             if (messageBias && replaceBiasMarkup(textareaText).trim().length === 0) { | ||||||
|                 sendSystemMessage(system_message_types.GENERIC, ' ', { bias: messageBias }); |                 sendSystemMessage(system_message_types.GENERIC, ' ', { bias: messageBias }); | ||||||
| @@ -2969,7 +2969,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, | |||||||
|                 await sendMessageAsUser(textareaText, messageBias); |                 await sendMessageAsUser(textareaText, messageBias); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         else if (textareaText == '' && !automatic_trigger && type === undefined && main_api == 'openai' && oai_settings.send_if_empty.trim().length > 0) { |         else if (textareaText == '' && !automatic_trigger && !dryRun && type === undefined && main_api == 'openai' && oai_settings.send_if_empty.trim().length > 0) { | ||||||
|             // Use send_if_empty if set and the user message is empty. Only when sending messages normally |             // Use send_if_empty if set and the user message is empty. Only when sending messages normally | ||||||
|             await sendMessageAsUser(oai_settings.send_if_empty.trim(), messageBias); |             await sendMessageAsUser(oai_settings.send_if_empty.trim(), messageBias); | ||||||
|         } |         } | ||||||
| @@ -4154,11 +4154,11 @@ async function DupeChar() { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const confirm = await callPopup(` |     const confirmMessage = ` | ||||||
|     <h3>Are you sure you want to duplicate this character?</h3> |     <h3>Are you sure you want to duplicate this character?</h3> | ||||||
|         <span>If you just want to start a new chat with the same character, use "Start new chat" option in the bottom-left options menu.</span><br><br>`, |     <span>If you just want to start a new chat with the same character, use "Start new chat" option in the bottom-left options menu.</span><br><br>`; | ||||||
|         'confirm', |  | ||||||
|     ); |     const confirm = await callPopup(confirmMessage, 'confirm'); | ||||||
|  |  | ||||||
|     if (!confirm) { |     if (!confirm) { | ||||||
|         console.log('User cancelled duplication'); |         console.log('User cancelled duplication'); | ||||||
| @@ -7631,10 +7631,7 @@ function doTogglePanels() { | |||||||
| } | } | ||||||
|  |  | ||||||
| function addDebugFunctions() { | function addDebugFunctions() { | ||||||
|     registerDebugFunction('backfillTokenCounts', 'Backfill token counters', |     const doBackfill = async () => { | ||||||
|         `Recalculates token counts of all messages in the current chat to refresh the counters. |  | ||||||
|         Useful when you switch between models that have different tokenizers. |  | ||||||
|         This is a visual change only. Your chat will be reloaded.`, async () => { |  | ||||||
|         for (const message of chat) { |         for (const message of chat) { | ||||||
|             // System messages are not counted |             // System messages are not counted | ||||||
|             if (message.is_system) { |             if (message.is_system) { | ||||||
| @@ -7650,7 +7647,12 @@ function addDebugFunctions() { | |||||||
|  |  | ||||||
|         await saveChatConditional(); |         await saveChatConditional(); | ||||||
|         await reloadCurrentChat(); |         await reloadCurrentChat(); | ||||||
|     }); |     }; | ||||||
|  |  | ||||||
|  |     registerDebugFunction('backfillTokenCounts', 'Backfill token counters', | ||||||
|  |         `Recalculates token counts of all messages in the current chat to refresh the counters. | ||||||
|  |         Useful when you switch between models that have different tokenizers. | ||||||
|  |         This is a visual change only. Your chat will be reloaded.`, doBackfill); | ||||||
|  |  | ||||||
|     registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => { |     registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => { | ||||||
|         const text = prompt('Input text:', 'Hello'); |         const text = prompt('Input text:', 'Hello'); | ||||||
|   | |||||||
| @@ -152,7 +152,7 @@ export async function populateFileAttachment(message, inputId = 'file_form_input | |||||||
|  */ |  */ | ||||||
| export async function uploadFileAttachment(fileName, base64Data) { | export async function uploadFileAttachment(fileName, base64Data) { | ||||||
|     try { |     try { | ||||||
|         const result = await fetch('/api/file/upload', { |         const result = await fetch('/api/files/upload', { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             headers: getRequestHeaders(), |             headers: getRequestHeaders(), | ||||||
|             body: JSON.stringify({ |             body: JSON.stringify({ | ||||||
| @@ -302,7 +302,7 @@ async function viewMessageFile(messageId) { | |||||||
|     modalTemplate.addClass('file_modal'); |     modalTemplate.addClass('file_modal'); | ||||||
|     addCopyToCodeBlocks(modalTemplate); |     addCopyToCodeBlocks(modalTemplate); | ||||||
|  |  | ||||||
|     callPopup(modalTemplate, 'text'); |     callPopup(modalTemplate, 'text', '', { wide: true, large: true }); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -666,7 +666,7 @@ async function CreateZenSliders(elmnt) { | |||||||
|         min: sliderMin, |         min: sliderMin, | ||||||
|         max: sliderMax, |         max: sliderMax, | ||||||
|         create: async function () { |         create: async function () { | ||||||
|             await delay(100) |             await delay(100); | ||||||
|             var handle = $(this).find('.ui-slider-handle'); |             var handle = $(this).find('.ui-slider-handle'); | ||||||
|             var handleText, stepNumber, leftMargin; |             var handleText, stepNumber, leftMargin; | ||||||
|  |  | ||||||
| @@ -711,7 +711,7 @@ async function CreateZenSliders(elmnt) { | |||||||
|                 stepNumber = ((sliderValue - sliderMin) / stepScale); |                 stepNumber = ((sliderValue - sliderMin) / stepScale); | ||||||
|                 leftMargin = (stepNumber / numSteps) * 50 * -1; |                 leftMargin = (stepNumber / numSteps) * 50 * -1; | ||||||
|                 originalSlider.val(numVal) |                 originalSlider.val(numVal) | ||||||
|                     .data('newSlider', newSlider) |                     .data('newSlider', newSlider); | ||||||
|                 //console.log(`${newSlider.attr('id')} sliderValue = ${sliderValue}, handleText:${handleText, numVal}, stepNum:${stepNumber}, numSteps:${numSteps}, left-margin:${leftMargin}`) |                 //console.log(`${newSlider.attr('id')} sliderValue = ${sliderValue}, handleText:${handleText, numVal}, stepNum:${stepNumber}, numSteps:${numSteps}, left-margin:${leftMargin}`) | ||||||
|                 var isManualInput = false; |                 var isManualInput = false; | ||||||
|                 var valueBeforeManualInput; |                 var valueBeforeManualInput; | ||||||
| @@ -737,8 +737,8 @@ async function CreateZenSliders(elmnt) { | |||||||
|                         isManualInput = true; |                         isManualInput = true; | ||||||
|                         //allow enter to trigger slider update |                         //allow enter to trigger slider update | ||||||
|                         if (e.key === 'Enter') { |                         if (e.key === 'Enter') { | ||||||
|                             e.preventDefault |                             e.preventDefault; | ||||||
|                             handle.trigger('blur') |                             handle.trigger('blur'); | ||||||
|                         } |                         } | ||||||
|                     }) |                     }) | ||||||
|                     //trigger slider changes when user clicks away |                     //trigger slider changes when user clicks away | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								server.js
									
									
									
									
									
								
							| @@ -3594,22 +3594,25 @@ require('./src/endpoints/thumbnails').registerEndpoints(app, jsonParser); | |||||||
| app.use('/api/novelai', require('./src/endpoints/novelai').router); | app.use('/api/novelai', require('./src/endpoints/novelai').router); | ||||||
|  |  | ||||||
| // Third-party extensions | // Third-party extensions | ||||||
| require('./src/endpoints/extensions').registerEndpoints(app, jsonParser); | app.use('/api/extensions', require('./src/endpoints/extensions').router); | ||||||
|  |  | ||||||
| // Asset management | // Asset management | ||||||
| require('./src/endpoints/assets').registerEndpoints(app, jsonParser); | app.use('/api/assets', require('./src/endpoints/assets').router); | ||||||
|  |  | ||||||
|  | // File management | ||||||
|  | app.use('/api/files', require('./src/endpoints/files').router); | ||||||
|  |  | ||||||
| // Character sprite management | // Character sprite management | ||||||
| require('./src/endpoints/sprites').registerEndpoints(app, jsonParser, urlencodedParser); | require('./src/endpoints/sprites').registerEndpoints(app, jsonParser, urlencodedParser); | ||||||
|  |  | ||||||
| // Custom content management | // Custom content management | ||||||
| require('./src/endpoints/content-manager').registerEndpoints(app, jsonParser); | app.use('/api/content', require('./src/endpoints/content-manager').router); | ||||||
|  |  | ||||||
| // Stable Diffusion generation | // Stable Diffusion generation | ||||||
| require('./src/endpoints/stable-diffusion').registerEndpoints(app, jsonParser); | require('./src/endpoints/stable-diffusion').registerEndpoints(app, jsonParser); | ||||||
|  |  | ||||||
| // LLM and SD Horde generation | // LLM and SD Horde generation | ||||||
| require('./src/endpoints/horde').registerEndpoints(app, jsonParser); | app.use('/api/horde', require('./src/endpoints/horde').router); | ||||||
|  |  | ||||||
| // Vector storage DB | // Vector storage DB | ||||||
| require('./src/endpoints/vectors').registerEndpoints(app, jsonParser); | require('./src/endpoints/vectors').registerEndpoints(app, jsonParser); | ||||||
| @@ -3618,10 +3621,10 @@ require('./src/endpoints/vectors').registerEndpoints(app, jsonParser); | |||||||
| require('./src/endpoints/translate').registerEndpoints(app, jsonParser); | require('./src/endpoints/translate').registerEndpoints(app, jsonParser); | ||||||
|  |  | ||||||
| // Emotion classification | // Emotion classification | ||||||
| require('./src/endpoints/classify').registerEndpoints(app, jsonParser); | app.use('/api/extra/classify', require('./src/endpoints/classify').router); | ||||||
|  |  | ||||||
| // Image captioning | // Image captioning | ||||||
| require('./src/endpoints/caption').registerEndpoints(app, jsonParser); | app.use('/api/extra/caption', require('./src/endpoints/caption').router); | ||||||
|  |  | ||||||
| // Web search extension | // Web search extension | ||||||
| require('./src/endpoints/serpapi').registerEndpoints(app, jsonParser); | require('./src/endpoints/serpapi').registerEndpoints(app, jsonParser); | ||||||
|   | |||||||
| @@ -1,10 +1,12 @@ | |||||||
| const path = require('path'); | const path = require('path'); | ||||||
| const fs = require('fs'); | const fs = require('fs'); | ||||||
|  | const express = require('express'); | ||||||
| const sanitize = require('sanitize-filename'); | const sanitize = require('sanitize-filename'); | ||||||
| const fetch = require('node-fetch').default; | const fetch = require('node-fetch').default; | ||||||
| const { finished } = require('stream/promises'); | const { finished } = require('stream/promises'); | ||||||
| const writeFileSyncAtomic = require('write-file-atomic').sync; | const writeFileSyncAtomic = require('write-file-atomic').sync; | ||||||
| const { DIRECTORIES, UNSAFE_EXTENSIONS } = require('../constants'); | const { DIRECTORIES, UNSAFE_EXTENSIONS } = require('../constants'); | ||||||
|  | const { jsonParser } = require('../express-common'); | ||||||
|  |  | ||||||
| const VALID_CATEGORIES = ['bgm', 'ambient', 'blip', 'live2d']; | const VALID_CATEGORIES = ['bgm', 'ambient', 'blip', 'live2d']; | ||||||
|  |  | ||||||
| @@ -57,12 +59,8 @@ function getFiles(dir, files = []) { | |||||||
|     return files; |     return files; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | const router = express.Router(); | ||||||
|  * Registers the endpoints for the asset management. |  | ||||||
|  * @param {import('express').Express} app Express app |  | ||||||
|  * @param {any} jsonParser JSON parser middleware |  | ||||||
|  */ |  | ||||||
| function registerEndpoints(app, jsonParser) { |  | ||||||
| /** | /** | ||||||
|  * HTTP POST handler function to retrieve name of all files of a given folder path. |  * HTTP POST handler function to retrieve name of all files of a given folder path. | ||||||
|  * |  * | ||||||
| @@ -71,7 +69,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/assets/get', jsonParser, async (_, response) => { | router.post('/get', jsonParser, async (_, response) => { | ||||||
|     const folderPath = path.join(DIRECTORIES.assets); |     const folderPath = path.join(DIRECTORIES.assets); | ||||||
|     let output = {}; |     let output = {}; | ||||||
|     //console.info("Checking files into",folderPath); |     //console.info("Checking files into",folderPath); | ||||||
| @@ -129,7 +127,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/assets/download', jsonParser, async (request, response) => { | router.post('/download', jsonParser, async (request, response) => { | ||||||
|     const url = request.body.url; |     const url = request.body.url; | ||||||
|     const inputCategory = request.body.category; |     const inputCategory = request.body.category; | ||||||
|     const inputFilename = sanitize(request.body.filename); |     const inputFilename = sanitize(request.body.filename); | ||||||
| @@ -189,7 +187,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/assets/delete', jsonParser, async (request, response) => { | router.post('/delete', jsonParser, async (request, response) => { | ||||||
|     const inputCategory = request.body.category; |     const inputCategory = request.body.category; | ||||||
|     const inputFilename = sanitize(request.body.filename); |     const inputFilename = sanitize(request.body.filename); | ||||||
|  |  | ||||||
| @@ -242,7 +240,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/assets/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); | ||||||
|     const name = sanitize(request.query.name.toString()); |     const name = sanitize(request.query.name.toString()); | ||||||
|     const inputCategory = request.query.category; |     const inputCategory = request.query.category; | ||||||
| @@ -297,7 +295,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|     app.post('/api/file/upload', jsonParser, async (request, response) => { | router.post('/upload', jsonParser, async (request, response) => { | ||||||
|     try { |     try { | ||||||
|         if (!request.body.name) { |         if (!request.body.name) { | ||||||
|             return response.status(400).send('No upload name specified'); |             return response.status(400).send('No upload name specified'); | ||||||
| @@ -322,8 +320,5 @@ function registerEndpoints(app, jsonParser) { | |||||||
|         return response.sendStatus(500); |         return response.sendStatus(500); | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { router, checkAssetFileName }; | ||||||
|     registerEndpoints, |  | ||||||
| }; |  | ||||||
|   | |||||||
| @@ -1,11 +1,11 @@ | |||||||
|  | const express = require('express'); | ||||||
|  | const { jsonParser } = require('../express-common'); | ||||||
|  |  | ||||||
| const TASK = 'image-to-text'; | const TASK = 'image-to-text'; | ||||||
|  |  | ||||||
| /** | const router = express.Router(); | ||||||
|  * @param {import("express").Express} app |  | ||||||
|  * @param {any} jsonParser | router.post('/', jsonParser, async (req, res) => { | ||||||
|  */ |  | ||||||
| function registerEndpoints(app, jsonParser) { |  | ||||||
|     app.post('/api/extra/caption', jsonParser, async (req, res) => { |  | ||||||
|     try { |     try { | ||||||
|         const { image } = req.body; |         const { image } = req.body; | ||||||
|  |  | ||||||
| @@ -28,8 +28,5 @@ function registerEndpoints(app, jsonParser) { | |||||||
|         return res.sendStatus(500); |         return res.sendStatus(500); | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { router }; | ||||||
|     registerEndpoints, |  | ||||||
| }; |  | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
|  | const express = require('express'); | ||||||
|  | const { jsonParser } = require('../express-common'); | ||||||
|  |  | ||||||
| const TASK = 'text-classification'; | const TASK = 'text-classification'; | ||||||
|  |  | ||||||
| /** | const router = express.Router(); | ||||||
|  * @param {import("express").Express} app |  | ||||||
|  * @param {any} jsonParser |  | ||||||
|  */ |  | ||||||
| function registerEndpoints(app, jsonParser) { |  | ||||||
| const cacheObject = {}; | const cacheObject = {}; | ||||||
|  |  | ||||||
|     app.post('/api/extra/classify/labels', jsonParser, async (req, res) => { | router.post('/labels', jsonParser, async (req, res) => { | ||||||
|     try { |     try { | ||||||
|         const module = await import('../transformers.mjs'); |         const module = await import('../transformers.mjs'); | ||||||
|         const pipe = await module.default.getPipeline(TASK); |         const pipe = await module.default.getPipeline(TASK); | ||||||
| @@ -19,7 +19,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|     app.post('/api/extra/classify', jsonParser, async (req, res) => { | router.post('/', jsonParser, async (req, res) => { | ||||||
|     try { |     try { | ||||||
|         const { text } = req.body; |         const { text } = req.body; | ||||||
|  |  | ||||||
| @@ -46,8 +46,5 @@ function registerEndpoints(app, jsonParser) { | |||||||
|         return res.sendStatus(500); |         return res.sendStatus(500); | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { router }; | ||||||
|     registerEndpoints, |  | ||||||
| }; |  | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| const fs = require('fs'); | const fs = require('fs'); | ||||||
| const path = require('path'); | const path = require('path'); | ||||||
|  | const express = require('express'); | ||||||
| const fetch = require('node-fetch').default; | const fetch = require('node-fetch').default; | ||||||
| const sanitize = require('sanitize-filename'); | const sanitize = require('sanitize-filename'); | ||||||
| const { getConfigValue } = require('../util'); | const { getConfigValue } = require('../util'); | ||||||
|  | const { jsonParser } = require('../express-common'); | ||||||
| const contentDirectory = path.join(process.cwd(), 'default/content'); | const contentDirectory = path.join(process.cwd(), 'default/content'); | ||||||
| const contentLogPath = path.join(contentDirectory, 'content.log'); | const contentLogPath = path.join(contentDirectory, 'content.log'); | ||||||
| const contentIndexPath = path.join(contentDirectory, 'index.json'); | const contentIndexPath = path.join(contentDirectory, 'index.json'); | ||||||
| @@ -302,13 +304,9 @@ function parseJannyUrl(url) { | |||||||
|     return uuid; |     return uuid; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | const router = express.Router(); | ||||||
|  * Registers endpoints for custom content management |  | ||||||
|  * @param {import('express').Express} app Express app | router.post('/import', jsonParser, async (request, response) => { | ||||||
|  * @param {any} jsonParser JSON parser middleware |  | ||||||
|  */ |  | ||||||
| function registerEndpoints(app, jsonParser) { |  | ||||||
|     app.post('/api/content/import', jsonParser, async (request, response) => { |  | ||||||
|     if (!request.body.url) { |     if (!request.body.url) { | ||||||
|         return response.sendStatus(400); |         return response.sendStatus(400); | ||||||
|     } |     } | ||||||
| @@ -353,11 +351,10 @@ function registerEndpoints(app, jsonParser) { | |||||||
|         return response.sendStatus(500); |         return response.sendStatus(500); | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     checkForNewContent, |     checkForNewContent, | ||||||
|     registerEndpoints, |  | ||||||
|     getDefaultPresets, |     getDefaultPresets, | ||||||
|     getDefaultPresetFile, |     getDefaultPresetFile, | ||||||
|  |     router, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| const path = require('path'); | const path = require('path'); | ||||||
| const fs = require('fs'); | const fs = require('fs'); | ||||||
|  | const express = require('express'); | ||||||
| const { default: simpleGit } = require('simple-git'); | const { default: simpleGit } = require('simple-git'); | ||||||
| const sanitize = require('sanitize-filename'); | const sanitize = require('sanitize-filename'); | ||||||
| const { DIRECTORIES } = require('../constants'); | const { DIRECTORIES } = require('../constants'); | ||||||
|  | const { jsonParser } = require('../express-common'); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This function extracts the extension information from the manifest file. |  * This function extracts the extension information from the manifest file. | ||||||
| @@ -45,12 +47,8 @@ async function checkIfRepoIsUpToDate(extensionPath) { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | const router = express.Router(); | ||||||
|  * Registers the endpoints for the third-party extensions API. |  | ||||||
|  * @param {import('express').Express} app - Express app |  | ||||||
|  * @param {any} jsonParser - JSON parser middleware |  | ||||||
|  */ |  | ||||||
| function registerEndpoints(app, jsonParser) { |  | ||||||
| /** | /** | ||||||
|  * HTTP POST handler function to clone a git repository from a provided URL, read the extension manifest, |  * HTTP POST handler function to clone a git repository from a provided URL, read the extension manifest, | ||||||
|  * and return extension information and path. |  * and return extension information and path. | ||||||
| @@ -60,7 +58,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/extensions/install', jsonParser, async (request, response) => { | router.post('/install', jsonParser, async (request, response) => { | ||||||
|     if (!request.body.url) { |     if (!request.body.url) { | ||||||
|         return response.status(400).send('Bad Request: URL is required in the request body.'); |         return response.status(400).send('Bad Request: URL is required in the request body.'); | ||||||
|     } |     } | ||||||
| @@ -105,7 +103,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/extensions/update', jsonParser, async (request, response) => { | router.post('/update', jsonParser, async (request, response) => { | ||||||
|     const git = simpleGit(); |     const git = simpleGit(); | ||||||
|     if (!request.body.extensionName) { |     if (!request.body.extensionName) { | ||||||
|         return response.status(400).send('Bad Request: extensionName is required in the request body.'); |         return response.status(400).send('Bad Request: extensionName is required in the request body.'); | ||||||
| @@ -150,7 +148,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/extensions/version', jsonParser, async (request, response) => { | router.post('/version', jsonParser, async (request, response) => { | ||||||
|     const git = simpleGit(); |     const git = simpleGit(); | ||||||
|     if (!request.body.extensionName) { |     if (!request.body.extensionName) { | ||||||
|         return response.status(400).send('Bad Request: extensionName is required in the request body.'); |         return response.status(400).send('Bad Request: extensionName is required in the request body.'); | ||||||
| @@ -188,7 +186,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * |  * | ||||||
|  * @returns {void} |  * @returns {void} | ||||||
|  */ |  */ | ||||||
|     app.post('/api/extensions/delete', jsonParser, async (request, response) => { | router.post('/delete', jsonParser, async (request, response) => { | ||||||
|     if (!request.body.extensionName) { |     if (!request.body.extensionName) { | ||||||
|         return response.status(400).send('Bad Request: extensionName is required in the request body.'); |         return response.status(400).send('Bad Request: extensionName is required in the request body.'); | ||||||
|     } |     } | ||||||
| @@ -218,8 +216,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  * Discover the extension folders |  * Discover the extension folders | ||||||
|  * If the folder is called third-party, search for subfolders instead |  * If the folder is called third-party, search for subfolders instead | ||||||
|  */ |  */ | ||||||
|     app.get('/api/extensions/discover', jsonParser, function (_, response) { | router.get('/discover', jsonParser, function (_, response) { | ||||||
|  |  | ||||||
|     // get all folders in the extensions folder, except third-party |     // get all folders in the extensions folder, except third-party | ||||||
|     const extensions = fs |     const extensions = fs | ||||||
|         .readdirSync(DIRECTORIES.extensions) |         .readdirSync(DIRECTORIES.extensions) | ||||||
| @@ -243,8 +240,5 @@ function registerEndpoints(app, jsonParser) { | |||||||
|  |  | ||||||
|     return response.send(extensions); |     return response.send(extensions); | ||||||
| }); | }); | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { router }; | ||||||
|     registerEndpoints, |  | ||||||
| }; |  | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								src/endpoints/files.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/endpoints/files.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | const path = require('path'); | ||||||
|  | const writeFileSyncAtomic = require('write-file-atomic').sync; | ||||||
|  | const express = require('express'); | ||||||
|  | const router = express.Router(); | ||||||
|  | const { checkAssetFileName } = require('./assets'); | ||||||
|  | const { jsonParser } = require('../express-common'); | ||||||
|  | const { DIRECTORIES } = require('../constants'); | ||||||
|  |  | ||||||
|  | router.post('/upload', jsonParser, async (request, response) => { | ||||||
|  |     try { | ||||||
|  |         if (!request.body.name) { | ||||||
|  |             return response.status(400).send('No upload name specified'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!request.body.data) { | ||||||
|  |             return response.status(400).send('No upload data specified'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const safeInput = checkAssetFileName(request.body.name); | ||||||
|  |  | ||||||
|  |         if (!safeInput) { | ||||||
|  |             return response.status(400).send('Invalid upload name'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const pathToUpload = path.join(DIRECTORIES.files, safeInput); | ||||||
|  |         writeFileSyncAtomic(pathToUpload, request.body.data, 'base64'); | ||||||
|  |         const url = path.normalize(pathToUpload.replace('public' + path.sep, '')); | ||||||
|  |         return response.send({ path: url }); | ||||||
|  |     } catch (error) { | ||||||
|  |         console.log(error); | ||||||
|  |         return response.sendStatus(500); | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | module.exports = { router }; | ||||||
| @@ -1,7 +1,9 @@ | |||||||
| const fetch = require('node-fetch').default; | const fetch = require('node-fetch').default; | ||||||
|  | const express = require('express'); | ||||||
| const AIHorde = require('../ai_horde'); | const AIHorde = require('../ai_horde'); | ||||||
| const { getVersion, delay } = require('../util'); | const { getVersion, delay } = require('../util'); | ||||||
| const { readSecret, SECRET_KEYS } = require('./secrets'); | const { readSecret, SECRET_KEYS } = require('./secrets'); | ||||||
|  | const { jsonParser } = require('../express-common'); | ||||||
|  |  | ||||||
| const ANONYMOUS_KEY = '0000000000'; | const ANONYMOUS_KEY = '0000000000'; | ||||||
|  |  | ||||||
| @@ -52,13 +54,9 @@ function sanitizeHordeImagePrompt(prompt) { | |||||||
|     return prompt; |     return prompt; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | const router = express.Router(); | ||||||
|  * |  | ||||||
|  * @param {import("express").Express} app | router.post('/generate-text', jsonParser, async (request, response) => { | ||||||
|  * @param {any} jsonParser |  | ||||||
|  */ |  | ||||||
| function registerEndpoints(app, jsonParser) { |  | ||||||
|     app.post('/api/horde/generate-text', jsonParser, async (request, response) => { |  | ||||||
|     const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY; |     const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY; | ||||||
|     const url = 'https://horde.koboldai.net/api/v2/generate/text/async'; |     const url = 'https://horde.koboldai.net/api/v2/generate/text/async'; | ||||||
|  |  | ||||||
| @@ -88,7 +86,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|     app.post('/api/horde/sd-samplers', jsonParser, async (_, response) => { | router.post('/sd-samplers', jsonParser, async (_, response) => { | ||||||
|     try { |     try { | ||||||
|         const ai_horde = await getHordeClient(); |         const ai_horde = await getHordeClient(); | ||||||
|         const samplers = Object.values(ai_horde.ModelGenerationInputStableSamplers); |         const samplers = Object.values(ai_horde.ModelGenerationInputStableSamplers); | ||||||
| @@ -99,7 +97,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|     app.post('/api/horde/sd-models', jsonParser, async (_, response) => { | router.post('/sd-models', jsonParser, async (_, response) => { | ||||||
|     try { |     try { | ||||||
|         const ai_horde = await getHordeClient(); |         const ai_horde = await getHordeClient(); | ||||||
|         const models = await ai_horde.getModels(); |         const models = await ai_horde.getModels(); | ||||||
| @@ -110,7 +108,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|     app.post('/api/horde/caption-image', jsonParser, async (request, response) => { | router.post('/caption-image', jsonParser, async (request, response) => { | ||||||
|     try { |     try { | ||||||
|         const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY; |         const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY; | ||||||
|         const ai_horde = await getHordeClient(); |         const ai_horde = await getHordeClient(); | ||||||
| @@ -162,7 +160,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|     app.post('/api/horde/user-info', jsonParser, async (_, response) => { | router.post('/user-info', jsonParser, async (_, response) => { | ||||||
|     const api_key_horde = readSecret(SECRET_KEYS.HORDE); |     const api_key_horde = readSecret(SECRET_KEYS.HORDE); | ||||||
|  |  | ||||||
|     if (!api_key_horde) { |     if (!api_key_horde) { | ||||||
| @@ -179,7 +177,7 @@ function registerEndpoints(app, jsonParser) { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|     app.post('/api/horde/generate-image', jsonParser, async (request, response) => { | router.post('/generate-image', jsonParser, async (request, response) => { | ||||||
|     if (!request.body.prompt) { |     if (!request.body.prompt) { | ||||||
|         return response.sendStatus(400); |         return response.sendStatus(400); | ||||||
|     } |     } | ||||||
| @@ -265,8 +263,5 @@ function registerEndpoints(app, jsonParser) { | |||||||
|         return response.sendStatus(500); |         return response.sendStatus(500); | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { router }; | ||||||
|     registerEndpoints, |  | ||||||
| }; |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user