Allow extensions to specify minimum ST client version (#4350) * allow extensions to specify minimum client version * using existing version compare function * Move versionCompare to utils module --------- Co-authored-by: qvink <qvink@users.noreply.github.com> Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -1,10 +1,10 @@ | ||
| 1 | 1 | import { DOMPurify, Popper } from '../lib.js'; |
| 2 | 2 | |
| 3 | 3 | import { eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders, animation_duration, CLIENT_VERSION } from '../script.js'; |
| 4 | 4 | import { showLoader } from './loader.js'; |
| 5 | 5 | import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js'; |
| 6 | 6 | import { renderTemplate, renderTemplateAsync } from './templates.js'; |
| 7 | 7 | import { delay, isSubsetOf, sanitizeSelector, setValueByPath, versionCompare } from './utils.js'; |
| 8 | 8 | import { getContext } from './st-context.js'; |
| 9 | 9 | import { isAdmin } from './user.js'; |
| 10 | 10 | import { addLocaleData, getCurrentLocale, t } from './i18n.js'; |
| @@ -387,6 +387,7 @@ async function getManifests(names) { | ||
| 387 | 387 | */ |
| 388 | 388 | async function activateExtensions() { |
| 389 | 389 | extensionLoadErrors.clear(); |
| 390 | + const clientVersion = CLIENT_VERSION.split(':')[1]; | |
| 390 | 391 | const extensions = Object.entries(manifests).sort((a, b) => sortManifestsByOrder(a[1], b[1])); |
| 391 | 392 | const extensionNames = extensions.map(x => x[0]); |
| 392 | 393 | const promises = []; |
| @@ -396,11 +397,17 @@ async function activateExtensions() { | ||
| 396 | 397 | const manifest = entry[1]; |
| 397 | 398 | const extrasRequirements = manifest.requires; |
| 398 | 399 | const extensionDependencies = manifest.dependencies; |
| 400 | + const minClientVersion = manifest.minimum_client_version; | |
| 399 | 401 | const displayName = manifest.display_name || name; |
| 400 | 402 | |
| 401 | 403 | if (activeExtensions.has(name)) { |
| 402 | 404 | continue; |
| 403 | 405 | } |
| 406 | + // Client version requirement: pass if 'minimum_client_version' is undefined or null. | |
| 407 | + let meetsClientMinimumVersion = true; | |
| 408 | + if (minClientVersion !== undefined) { | |
| 409 | + meetsClientMinimumVersion = versionCompare(clientVersion, minClientVersion); | |
| 410 | + } | |
| 404 | 411 | |
| 405 | 412 | // Module requirements: pass if 'requires' is undefined, null, or not an array; check subset if it's an array |
| 406 | 413 | let meetsModuleRequirements = true; |
| @@ -438,7 +445,7 @@ async function activateExtensions() { | ||
| 438 | 445 | |
| 439 | 446 | const isDisabled = extension_settings.disabledExtensions.includes(name); |
| 440 | 447 | |
| 441 | 448 | if (meetsModuleRequirements && meetsExtensionDeps && meetsClientMinimumVersion && !isDisabled) { |
| 442 | 449 | try { |
| 443 | 450 | console.debug('Activating extension', name); |
| 444 | 451 | const promise = addExtensionLocale(name, manifest).finally(() => |
| @@ -465,6 +472,9 @@ async function activateExtensions() { | ||
| 465 | 472 | console.warn(t`Extension "${name}" did not load. Missing required extensions: "${missingDependencies.join(', ')}"`); |
| 466 | 473 | extensionLoadErrors.add(t`Extension "${displayName}" did not load. Missing required extensions: "${missingDependencies.join(', ')}"`); |
| 467 | 474 | } |
| 475 | + } else if (!meetsClientMinimumVersion && !isDisabled) { | |
| 476 | + console.warn(t`Extension "${name}" did not load. Requires ST client version ${minClientVersion}, but current version is ${clientVersion}.`); | |
| 477 | + extensionLoadErrors.add(t`Extension "${displayName}" did not load. Requires ST client version ${minClientVersion}, but current version is ${clientVersion}.`); | |
| 468 | 478 | } |
| 469 | 479 | } |
| 470 | 480 | |
| @@ -20,7 +20,7 @@ import { | ||
| 20 | 20 | power_user, |
| 21 | 21 | } from './power-user.js'; |
| 22 | 22 | import { getEventSourceStream } from './sse-stream.js'; |
| 23 | 23 | import { getSortableDelay, versionCompare } from './utils.js'; |
| 24 | 24 | |
| 25 | 25 | export let koboldai_settings; |
| 26 | 26 | export let koboldai_setting_names; |
| @@ -389,16 +389,6 @@ export function setKoboldFlags(koboldUnitedVersion, koboldCppVersion) { | ||
| 389 | 389 | } |
| 390 | 390 | |
| 391 | 391 | /** |
| 392 | - * Compares two version numbers, returning true if srcVersion >= minVersion | |
| 393 | - * @param {string} srcVersion The current version. | |
| 394 | - * @param {string} minVersion The target version number to test against | |
| 395 | - * @returns {boolean} True if srcVersion >= minVersion, false if not | |
| 396 | - */ | |
| 397 | -function versionCompare(srcVersion, minVersion) { | |
| 398 | - return (srcVersion || '0.0.0').localeCompare(minVersion, undefined, { numeric: true, sensitivity: 'base' }) > -1; | |
| 399 | -} | |
| 400 | - | |
| 401 | -/** | |
| 402 | 392 | * Sorts the sampler items by the given order. |
| 403 | 393 | * @param {any[]} orderArray Sampler order array. |
| 404 | 394 | */ |
| @@ -2550,3 +2550,13 @@ export function textValueMatcher(params, data) { | ||
| 2550 | 2550 | // If it doesn't contain the term, don't return anything |
| 2551 | 2551 | return null; |
| 2552 | 2552 | } |
| 2553 | + | |
| 2554 | +/** | |
| 2555 | + * Compares two version numbers, returning true if srcVersion >= minVersion | |
| 2556 | + * @param {string} srcVersion The current version. | |
| 2557 | + * @param {string} minVersion The target version number to test against | |
| 2558 | + * @returns {boolean} True if srcVersion >= minVersion, false if not | |
| 2559 | + */ | |
| 2560 | +export function versionCompare(srcVersion, minVersion) { | |
| 2561 | + return (srcVersion || '0.0.0').localeCompare(minVersion, undefined, { numeric: true, sensitivity: 'base' }) > -1; | |
| 2562 | +} | |