diff --git a/package-lock.json b/package-lock.json index 3941462d2..19eb2d6fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sillytavern", - "version": "1.10.5", + "version": "1.10.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sillytavern", - "version": "1.10.5", + "version": "1.10.6", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index d2c9b7dd3..185af0b1d 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "type": "git", "url": "https://github.com/SillyTavern/SillyTavern.git" }, - "version": "1.10.5", + "version": "1.10.6", "scripts": { "start": "node server.js", "start-multi": "node server.js --disableCsrf", diff --git a/public/script.js b/public/script.js index 06374aa02..dc718241d 100644 --- a/public/script.js +++ b/public/script.js @@ -339,6 +339,7 @@ export let isChatSaving = false; let chat_create_date = 0; let firstRun = false; let settingsReady = false; +let currentVersion = "0.0.0"; const default_ch_mes = "Hello"; let count_view_mes = 0; @@ -537,6 +538,7 @@ async function getClientVersion() { const data = await response.json(); CLIENT_VERSION = data.agent; let displayVersion = `SillyTavern ${data.pkgVersion}`; + currentVersion = data.pkgVersion; if (data.gitRevision && data.gitBranch) { displayVersion += ` '${data.gitBranch}' (${data.gitRevision})`; @@ -5045,7 +5047,8 @@ async function getSettings(type) { selected_button = settings.selected_button; if (data.enable_extensions) { - await loadExtensionSettings(settings); + const isVersionChanged = settings.currentVersion !== currentVersion; + await loadExtensionSettings(settings, isVersionChanged); eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED); } } @@ -5071,6 +5074,7 @@ async function saveSettings(type) { url: "/savesettings", data: JSON.stringify({ firstRun: firstRun, + currentVersion: currentVersion, username: name1, active_character: active_character, active_group: active_group, diff --git a/public/scripts/extensions.js b/public/scripts/extensions.js index c62a24e5c..76c3c2b64 100644 --- a/public/scripts/extensions.js +++ b/public/scripts/extensions.js @@ -609,6 +609,15 @@ async function showExtensionsDetails() { */ async function onUpdateClick() { const extensionName = $(this).data('name'); + await updateExtension(extensionName, false); +} + +/** + * Updates a third-party extension via the API. + * @param {string} extensionName Extension folder name + * @param {boolean} quiet If true, don't show a success message + */ +async function updateExtension(extensionName, quiet) { try { const response = await fetch('/api/extensions/update', { method: 'POST', @@ -618,15 +627,20 @@ async function onUpdateClick() { const data = await response.json(); if (data.isUpToDate) { - toastr.success('Extension is already up to date'); + if (!quiet) { + toastr.success('Extension is already up to date'); + } } else { - toastr.success(`Extension updated to ${data.shortCommitHash}`); + toastr.success(`Extension ${extensionName} updated to ${data.shortCommitHash}`); + } + + if (!quiet) { + showExtensionsDetails(); } - showExtensionsDetails(); } catch (error) { console.error('Error:', error); } -}; +} /** * Handles the click event for the delete button of an extension. @@ -706,11 +720,16 @@ export async function installExtension(url) { const response = await request.json(); toastr.success(`Extension "${response.display_name}" by ${response.author} (version ${response.version}) has been imported successfully!`, 'Extension import successful'); console.debug(`Extension "${response.display_name}" has been imported successfully at ${response.extensionPath}`); - await loadExtensionSettings({}); + await loadExtensionSettings({}, false); eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED); } -async function loadExtensionSettings(settings) { +/** + * Loads extension settings from the app settings. + * @param {object} settings App Settings + * @param {boolean} versionChanged Is this a version change? + */ +async function loadExtensionSettings(settings, versionChanged) { if (settings.extension_settings) { Object.assign(extension_settings, settings.extension_settings); } @@ -723,10 +742,25 @@ async function loadExtensionSettings(settings) { eventSource.emit(event_types.EXTENSIONS_FIRST_LOAD); extensionNames = await discoverExtensions(); manifests = await getManifests(extensionNames) + + if (versionChanged) { + await autoUpdateExtensions(); + } + await activateExtensions(); if (extension_settings.autoConnect && extension_settings.apiUrl) { connectToApi(extension_settings.apiUrl); } + +} + +async function autoUpdateExtensions() { + for (const [id, manifest] of Object.entries(manifests)) { + if (manifest.auto_update && id.startsWith('third-party')) { + console.debug(`Auto-updating 3rd-party extension: ${manifest.display_name} (${id})`); + await updateExtension(id.replace('third-party', ''), true); + } + } } async function runGenerationInterceptors(chat, contextSize) {