Migrate only unique and non-default instruct prompts
| @@ -219,6 +219,37 @@ function getContentIndex() { | |||
| 219 | } | 219 | } |
| 220 | 220 | ||
| 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 | */ | ||
| 227 | function 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 type | 254 | * @param {ContentType} type Asset type |
| 224 | * @param {import('../users').UserDirectoryList} directories User directories | 255 | * @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 | }; |
| @@ -10,6 +10,7 @@ const express = require('express'); | |||
| 10 | const mime = require('mime-types'); | 10 | const mime = require('mime-types'); |
| 11 | const archiver = require('archiver'); | 11 | const archiver = require('archiver'); |
| 12 | const writeFileAtomicSync = require('write-file-atomic').sync; | 12 | const writeFileAtomicSync = require('write-file-atomic').sync; |
| 13 | const _ = require('lodash'); | ||
| 13 | 14 | ||
| 14 | const { USER_DIRECTORY_TEMPLATE, DEFAULT_USER, PUBLIC_DIRECTORIES, SETTINGS_FILE } = require('./constants'); | 15 | const { USER_DIRECTORY_TEMPLATE, DEFAULT_USER, PUBLIC_DIRECTORIES, SETTINGS_FILE } = require('./constants'); |
| 15 | const { getConfigValue, color, delay, setConfigValue, generateTimestamp } = require('./util'); | 16 | const { getConfigValue, color, delay, setConfigValue, generateTimestamp } = require('./util'); |
| @@ -326,6 +327,19 @@ async function migrateUserData() { | |||
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | async function migrateSystemPrompts() { | 329 | async 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 errors | 377 | // Ignore errors |