Migrate only unique and non-default instruct prompts

4b235f0b3159ae90007715f7f1bb709550e05c6a

Cohee <18619528+Cohee1207@users.noreply.github.com>

2 files changed, +60 -4Showing whitespace changes
src/endpoints/content-manager.js+32 -0
@@ -219,6 +219,37 @@ function getContentIndex() {
219}219}
220220
221/**221/**
222 * Gets content by type and format.
223 * @param {string} type Type of content
224 * @param {'json'|'string'|'raw'} format Format of content
225 * @returns {string[]|Buffer[]} Array of content
226 */
227function getContentOfType(type, format) {
228 const contentIndex = getContentIndex();
229 const indexItems = contentIndex.filter((item) => item.type === type && item.folder);
230 const files = [];
231 for (const item of indexItems) {
232 if (!item.folder) {
233 continue;
234 }
235 const filePath = path.join(item.folder, item.filename);
236 const fileContent = fs.readFileSync(filePath);
237 switch (format) {
238 case 'json':
239 files.push(JSON.parse(fileContent.toString()));
240 break;
241 case 'string':
242 files.push(fileContent.toString());
243 break;
244 case 'raw':
245 files.push(fileContent);
246 break;
247 }
248 }
249 return files;
250}
251
252/**
222 * Gets the target directory for the specified asset type.253 * Gets the target directory for the specified asset type.
223 * @param {ContentType} type Asset type254 * @param {ContentType} type Asset type
224 * @param {import('../users').UserDirectoryList} directories User directories255 * @param {import('../users').UserDirectoryList} directories User directories
@@ -724,5 +755,6 @@ module.exports = {
724 checkForNewContent,755 checkForNewContent,
725 getDefaultPresets,756 getDefaultPresets,
726 getDefaultPresetFile,757 getDefaultPresetFile,
758 getContentOfType,
727 router,759 router,
728};760};
src/users.js+28 -4
@@ -10,6 +10,7 @@ const express = require('express');
10const mime = require('mime-types');10const mime = require('mime-types');
11const archiver = require('archiver');11const archiver = require('archiver');
12const writeFileAtomicSync = require('write-file-atomic').sync;12const writeFileAtomicSync = require('write-file-atomic').sync;
13const _ = require('lodash');
1314
14const { USER_DIRECTORY_TEMPLATE, DEFAULT_USER, PUBLIC_DIRECTORIES, SETTINGS_FILE } = require('./constants');15const { USER_DIRECTORY_TEMPLATE, DEFAULT_USER, PUBLIC_DIRECTORIES, SETTINGS_FILE } = require('./constants');
15const { getConfigValue, color, delay, setConfigValue, generateTimestamp } = require('./util');16const { getConfigValue, color, delay, setConfigValue, generateTimestamp } = require('./util');
@@ -326,6 +327,19 @@ async function migrateUserData() {
326}327}
327328
328async function migrateSystemPrompts() {329async function migrateSystemPrompts() {
330 /**
331 * Gets the default system prompts.
332 * @returns {Promise<any[]>} - The list of default system prompts
333 */
334 async function getDefaultSystemPrompts() {
335 try {
336 const { getContentOfType } = await import('./endpoints/content-manager.js');
337 return getContentOfType('sysprompt', 'json');
338 } catch {
339 return [];
340 }
341 }
342
329 const directories = await getUserDirectoriesList();343 const directories = await getUserDirectoriesList();
330 for (const directory of directories) {344 for (const directory of directories) {
331 try {345 try {
@@ -333,21 +347,31 @@ async function migrateSystemPrompts() {
333 if (fs.existsSync(migrateMarker)) {347 if (fs.existsSync(migrateMarker)) {
334 continue;348 continue;
335 }349 }
350 const defaultPrompts = await getDefaultSystemPrompts();
336 const instucts = fs.readdirSync(directory.instruct);351 const instucts = fs.readdirSync(directory.instruct);
352 let migratedPrompts = [];
337 for (const instruct of instucts) {353 for (const instruct of instucts) {
338 const instructPath = path.join(directory.instruct, instruct);354 const instructPath = path.join(directory.instruct, instruct);
339 const syspromptPath = path.join(directory.sysprompt, instruct);355 const sysPromptPath = path.join(directory.sysprompt, instruct);
340 if (path.extname(instruct) === '.json' && !fs.existsSync(syspromptPath)) {356 if (path.extname(instruct) === '.json' && !fs.existsSync(sysPromptPath)) {
341 const instructData = JSON.parse(fs.readFileSync(instructPath, 'utf8'));357 const instructData = JSON.parse(fs.readFileSync(instructPath, 'utf8'));
342 if ('system_prompt' in instructData && 'name' in instructData) {358 if ('system_prompt' in instructData && 'name' in instructData) {
343 const syspromptData = { name: instructData.name, content: instructData.system_prompt };359 const syspromptData = { name: instructData.name, content: instructData.system_prompt };
344 writeFileAtomicSync(syspromptPath, JSON.stringify(syspromptData, null, 4));360 migratedPrompts.push(syspromptData);
345 delete instructData.system_prompt;361 delete instructData.system_prompt;
346 writeFileAtomicSync(instructPath, JSON.stringify(instructData, null, 4));362 writeFileAtomicSync(instructPath, JSON.stringify(instructData, null, 4));
347 console.log(`Migrated system prompt ${instruct} for ${directory.root.split(path.sep).pop()}`);
348 }363 }
349 }364 }
350 }365 }
366 // Only leave unique contents
367 migratedPrompts = _.uniqBy(migratedPrompts, 'content');
368 // Only leave contents that are not in the default prompts
369 migratedPrompts = migratedPrompts.filter(x => !defaultPrompts.some(y => y.content === x.content));
370 for (const sysPromptData of migratedPrompts) {
371 const syspromptPath = path.join(directory.sysprompt, `${sysPromptData.name}.json`);
372 writeFileAtomicSync(syspromptPath, JSON.stringify(sysPromptData, null, 4));
373 console.log(`Migrated system prompt ${sysPromptData.name} for ${directory.root.split(path.sep).pop()}`);
374 }
351 writeFileAtomicSync(migrateMarker, '');375 writeFileAtomicSync(migrateMarker, '');
352 } catch {376 } catch {
353 // Ignore errors377 // Ignore errors