From fee36419acfcea963a226dfa4c2b1208244f4a0f Mon Sep 17 00:00:00 2001 From: Theros Date: Wed, 10 Jul 2024 23:41:06 +0100 Subject: [PATCH 01/20] Includes captioning error messages in toast --- public/scripts/extensions/caption/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/extensions/caption/index.js b/public/scripts/extensions/caption/index.js index b47f73a2f..c8ac72017 100644 --- a/public/scripts/extensions/caption/index.js +++ b/public/scripts/extensions/caption/index.js @@ -333,7 +333,7 @@ async function getCaptionForFile(file, prompt, quiet) { return caption; } catch (error) { - toastr.error('Failed to caption image.'); + toastr.error(`Failed to caption image. ${error}`); console.log(error); return ''; } From 51f09c13823bf84743e395dd9fb5b431e7022725 Mon Sep 17 00:00:00 2001 From: Theros Date: Thu, 11 Jul 2024 00:12:39 +0100 Subject: [PATCH 02/20] Changes: use Fail message as toast title, only show actual message with fallback. --- public/scripts/extensions/caption/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/scripts/extensions/caption/index.js b/public/scripts/extensions/caption/index.js index c8ac72017..dbfbc0d1d 100644 --- a/public/scripts/extensions/caption/index.js +++ b/public/scripts/extensions/caption/index.js @@ -333,8 +333,9 @@ async function getCaptionForFile(file, prompt, quiet) { return caption; } catch (error) { - toastr.error(`Failed to caption image. ${error}`); - console.log(error); + const errorMessage = error.message || 'Unknown error'; + toastr.error(errorMessage, "Failed to caption image."); + console.error(error); return ''; } finally { From 307a579f80202712cd76501927699ecd6ebd2910 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 11 Jul 2024 01:37:56 +0200 Subject: [PATCH 03/20] Move preset manager popups to new Popup --- public/scripts/preset-manager.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/public/scripts/preset-manager.js b/public/scripts/preset-manager.js index 90fe232ba..0176937b0 100644 --- a/public/scripts/preset-manager.js +++ b/public/scripts/preset-manager.js @@ -1,6 +1,5 @@ import { amount_gen, - callPopup, characters, eventSource, event_types, @@ -19,6 +18,7 @@ import { import { groups, selected_group } from './group-chats.js'; import { instruct_presets } from './instruct-mode.js'; import { kai_settings } from './kai-settings.js'; +import { Popup } from './popup.js'; import { context_presets, getContextSettings, power_user } from './power-user.js'; import { SlashCommand } from './slash-commands/SlashCommand.js'; import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashCommandArgument.js'; @@ -165,11 +165,8 @@ class PresetManager { async savePresetAs() { const inputValue = this.getSelectedPresetName(); - const popupText = ` -

Preset name:

- ${!this.isNonGenericApi() ? '

Hint: Use a character/group name to bind preset to a specific chat.

' : ''}`; - const name = await callPopup(popupText, 'input', inputValue); - + const popupText = !this.isNonGenericApi() ? '

Hint: Use a character/group name to bind preset to a specific chat.

' : ''; + const name = Popup.show.input('Preset name:', popupText, inputValue); if (!name) { console.log('Preset name not provided'); return; @@ -597,8 +594,7 @@ export async function initPresetManager() { return; } - const confirm = await callPopup('Delete the preset? This action is irreversible and your current settings will be overwritten.', 'confirm'); - + const confirm = await Popup.show.input('Delete the preset?', 'This action is irreversible and your current settings will be overwritten.'); if (!confirm) { return; } @@ -641,8 +637,7 @@ export async function initPresetManager() { return; } - const confirm = await callPopup('

Are you sure?

Resetting a default preset will restore the default settings.', 'confirm'); - + const confirm = await Popup.show.confirm('Are you sure?', 'Resetting a default preset will restore the default settings.'); if (!confirm) { return; } @@ -653,8 +648,7 @@ export async function initPresetManager() { presetManager.selectPreset(option); toastr.success('Default preset restored'); } else { - const confirm = await callPopup('

Are you sure?

Resetting a custom preset will restore to the last saved state.', 'confirm'); - + const confirm = await Popup.show.confirm('Are you sure?', 'Resetting a custom preset will restore to the last saved state.'); if (!confirm) { return; } From 3983eef8279ad461e8841e1df7301598194708bd Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 11 Jul 2024 01:38:28 +0200 Subject: [PATCH 04/20] fix linting issue --- public/scripts/preset-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/preset-manager.js b/public/scripts/preset-manager.js index 0176937b0..19c3f0bbd 100644 --- a/public/scripts/preset-manager.js +++ b/public/scripts/preset-manager.js @@ -369,7 +369,7 @@ class PresetManager { if (Object.keys(preset_names).length) { const nextPresetName = Object.keys(preset_names)[0]; const newValue = preset_names[nextPresetName]; - $(this.select).find(`option[value="${newValue}"]`).attr('selected', true); + $(this.select).find(`option[value="${newValue}"]`).attr('selected', 'true'); $(this.select).trigger('change'); } From 9754d5361f685492e167d5fb44cdfd44bd5ee15f Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 11 Jul 2024 15:37:30 +0000 Subject: [PATCH 05/20] Decreate edit textarea debounce duration --- public/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/script.js b/public/script.js index aa6e5f16b..ebd911738 100644 --- a/public/script.js +++ b/public/script.js @@ -9237,7 +9237,7 @@ jQuery(async function () { e.style.height = `${e.scrollHeight + 4}px`; is_use_scroll_holder = true; } - const autoFitEditTextAreaDebounced = debouncedThrottle(autoFitEditTextArea, debounce_timeout.standard); + const autoFitEditTextAreaDebounced = debouncedThrottle(autoFitEditTextArea, debounce_timeout.short); document.addEventListener('input', e => { if (e.target instanceof HTMLTextAreaElement && e.target.classList.contains('edit_textarea')) { const immediately = e.target.scrollHeight > e.target.offsetHeight || e.target.value === ''; From aadc8d74a24ce44dee4179ceff291066bd113efa Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 11 Jul 2024 21:05:42 +0300 Subject: [PATCH 06/20] #2513 Add 'mode' argument for /fuzzy --- public/scripts/slash-commands.js | 89 ++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 533ca5e36..e79ae9b31 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -952,14 +952,36 @@ export function initDefaultSlashCommands() { SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'fuzzy', callback: fuzzyCallback, - returns: 'first matching item', + returns: 'matching item', namedArgumentList: [ - new SlashCommandNamedArgument( - 'list', 'list of items to match against', [ARGUMENT_TYPE.LIST], true, - ), - new SlashCommandNamedArgument( - 'threshold', 'fuzzy match threshold (0.0 to 1.0)', [ARGUMENT_TYPE.NUMBER], false, false, '0.4', - ), + SlashCommandNamedArgument.fromProps({ + name: 'list', + description: 'list of items to match against', + acceptsMultiple: false, + isRequired: true, + typeList: [ARGUMENT_TYPE.LIST, ARGUMENT_TYPE.VARIABLE_NAME], + enumProvider: commonEnumProviders.variables('all'), + }), + SlashCommandNamedArgument.fromProps({ + name: 'threshold', + description: 'fuzzy match threshold (0.0 to 1.0)', + typeList: [ARGUMENT_TYPE.NUMBER], + isRequired: false, + defaultValue: '0.4', + acceptsMultiple: false, + }), + SlashCommandNamedArgument.fromProps({ + name: 'mode', + description: 'fuzzy match mode', + typeList: [ARGUMENT_TYPE.STRING], + isRequired: false, + defaultValue: 'first', + acceptsMultiple: false, + enumProvider: () => [ + new SlashCommandEnumValue('first', 'first match below the threshold', enumTypes.enum, enumIcons.default), + new SlashCommandEnumValue('best', 'best match below the threshold', enumTypes.enum, enumIcons.default), + ], + }), ], unnamedArgumentList: [ new SlashCommandArgument( @@ -976,6 +998,13 @@ export function initDefaultSlashCommands() { A low value (min 0.0) means the match is very strict. At 1.0 (max) the match is very loose and will match anything. +
+ The optional mode argument allows to control the behavior when multiple items match the text. +
    +
  • first (default) returns the first match below the threshold.
  • +
  • best returns the best match below the threshold.
  • +
+
The returned value passes to the next command through the pipe.
@@ -1865,7 +1894,7 @@ async function inputCallback(args, prompt) { * @param {FuzzyCommandArgs} args - arguments containing "list" (JSON array) and optionaly "threshold" (float between 0.0 and 1.0) * @param {string} searchInValue - the string where items of list are searched * @returns {string} - the matched item from the list - * @typedef {{list: string, threshold: string}} FuzzyCommandArgs - arguments for /fuzzy command + * @typedef {{list: string, threshold: string, mode:string}} FuzzyCommandArgs - arguments for /fuzzy command * @example /fuzzy list=["down","left","up","right"] "he looks up" | /echo // should return "up" * @link https://www.fusejs.io/ */ @@ -1895,7 +1924,7 @@ function fuzzyCallback(args, searchInValue) { }; // threshold determines how strict is the match, low threshold value is very strict, at 1 (nearly?) everything matches if ('threshold' in args) { - params.threshold = parseFloat(resolveVariable(args.threshold)); + params.threshold = parseFloat(args.threshold); if (isNaN(params.threshold)) { console.warn('WARN: \'threshold\' argument must be a float between 0.0 and 1.0 for /fuzzy command'); return ''; @@ -1908,16 +1937,42 @@ function fuzzyCallback(args, searchInValue) { } } - const fuse = new Fuse([searchInValue], params); - // each item in the "list" is searched within "search_item", if any matches it returns the matched "item" - for (const searchItem of list) { - const result = fuse.search(searchItem); - if (result.length > 0) { - console.info('fuzzyCallback Matched: ' + searchItem); - return searchItem; + function getFirstMatch() { + const fuse = new Fuse([searchInValue], params); + // each item in the "list" is searched within "search_item", if any matches it returns the matched "item" + for (const searchItem of list) { + const result = fuse.search(searchItem); + console.debug('/fuzzy: result', result); + if (result.length > 0) { + console.info('/fuzzy: first matched', searchItem); + return searchItem; + } } + + console.info('/fuzzy: no match'); + return ''; + } + + function getBestMatch() { + const fuse = new Fuse(list, params); + const result = fuse.search(searchInValue); + console.debug('/fuzzy: result', result); + if (result.length > 0) { + console.info('/fuzzy: best matched', result[0].item); + return result[0].item; + } + + console.info('/fuzzy: no match'); + return ''; + } + + switch (String(args.mode).trim().toLowerCase()) { + case 'best': + return getBestMatch(); + case 'first': + default: + return getFirstMatch(); } - return ''; } catch { console.warn('WARN: Invalid list argument provided for /fuzzy command'); return ''; From c4aed23cf73bb31b98af81916c77870c14ad2d22 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 11 Jul 2024 21:18:26 +0300 Subject: [PATCH 07/20] Don't overextend input textarea height on autofit --- public/scripts/RossAscends-mods.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js index dceba9063..5c56b3be5 100644 --- a/public/scripts/RossAscends-mods.js +++ b/public/scripts/RossAscends-mods.js @@ -31,7 +31,7 @@ import { SECRET_KEYS, secret_state, } from './secrets.js'; -import { debounce, getStringHash, isValidUrl } from './utils.js'; +import { debounce, debouncedThrottle, getStringHash, isValidUrl } from './utils.js'; import { chat_completion_sources, oai_settings } from './openai.js'; import { getTokenCountAsync } from './tokenizers.js'; import { textgen_types, textgenerationwebui_settings as textgen_settings, getTextGenServer } from './textgen-settings.js'; @@ -694,20 +694,23 @@ const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; * this makes the chat input text area resize vertically to match the text size (limited by CSS at 50% window height) */ function autoFitSendTextArea() { + // Needs to be pulled dynamically because it is affected by font size changes + const computedStyle = window.getComputedStyle(sendTextArea); const originalScrollBottom = chatBlock.scrollHeight - (chatBlock.scrollTop + chatBlock.offsetHeight); if (Math.ceil(sendTextArea.scrollHeight + 3) >= Math.floor(sendTextArea.offsetHeight)) { - // Needs to be pulled dynamically because it is affected by font size changes - const sendTextAreaMinHeight = window.getComputedStyle(sendTextArea).getPropertyValue('min-height'); + const sendTextAreaMinHeight = computedStyle.minHeight; sendTextArea.style.height = sendTextAreaMinHeight; } - sendTextArea.style.height = sendTextArea.scrollHeight + 3 + 'px'; + const maxHeight = parseInt(computedStyle.maxHeight, 10); + const newHeight = sendTextArea.scrollHeight + 3; + sendTextArea.style.height = (newHeight < maxHeight) ? `${newHeight}px` : `${maxHeight}px`; if (!isFirefox) { const newScrollTop = Math.round(chatBlock.scrollHeight - (chatBlock.offsetHeight + originalScrollBottom)); chatBlock.scrollTop = newScrollTop; } } -export const autoFitSendTextAreaDebounced = debounce(autoFitSendTextArea); +export const autoFitSendTextAreaDebounced = debouncedThrottle(autoFitSendTextArea, debounce_timeout.short); // --------------------------------------------------- From 4895b6def89057dcf12ecdc14854eaea4788c3e3 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 11 Jul 2024 21:19:09 +0300 Subject: [PATCH 08/20] Use enumList for /fuzzy --- public/scripts/slash-commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index e79ae9b31..71d8c894a 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -977,7 +977,7 @@ export function initDefaultSlashCommands() { isRequired: false, defaultValue: 'first', acceptsMultiple: false, - enumProvider: () => [ + enumList: [ new SlashCommandEnumValue('first', 'first match below the threshold', enumTypes.enum, enumIcons.default), new SlashCommandEnumValue('best', 'best match below the threshold', enumTypes.enum, enumIcons.default), ], From e22b18ce809f569960d302db78a8784da6f1a440 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 11 Jul 2024 21:25:52 +0300 Subject: [PATCH 09/20] Don't overextend edit textarea height --- public/script.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/public/script.js b/public/script.js index ebd911738..f6cf2dba9 100644 --- a/public/script.js +++ b/public/script.js @@ -9232,9 +9232,12 @@ jQuery(async function () { * @param {HTMLTextAreaElement} e Textarea element to auto-fit */ function autoFitEditTextArea(e) { + const computedStyle = window.getComputedStyle(e); + const maxHeight = parseInt(computedStyle.maxHeight, 10); + const newHeight = e.scrollHeight + 4; scroll_holder = chatElement[0].scrollTop; - e.style.height = '0'; - e.style.height = `${e.scrollHeight + 4}px`; + e.style.height = computedStyle.minHeight; + e.style.height = (newHeight < maxHeight) ? `${newHeight}px` : `${maxHeight}px`; is_use_scroll_holder = true; } const autoFitEditTextAreaDebounced = debouncedThrottle(autoFitEditTextArea, debounce_timeout.short); From a6e58845ccb3aca20a9f79089e93cb7e0b845191 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 11 Jul 2024 21:35:39 +0300 Subject: [PATCH 10/20] #2515 Use /cut in /del --- public/scripts/power-user.js | 53 ++++++++++++------------------------ 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js index f57de63ff..08fbfb504 100644 --- a/public/scripts/power-user.js +++ b/public/scripts/power-user.js @@ -2734,45 +2734,26 @@ async function doDelMode(_, text) { return ''; } - //first enter delmode - $('#option_delete_mes').trigger('click', { fromSlashCommand: true }); - - //parse valid args - if (text) { - await delay(300); //same as above, need event signal for 'entered del mode' - console.debug('parsing msgs to del'); - let numMesToDel = Number(text); - let lastMesID = Number($('#chat .mes').last().attr('mesid')); - let oldestMesIDToDel = lastMesID - numMesToDel + 1; - - if (oldestMesIDToDel < 0) { - toastr.warning(`Cannot delete more than ${chat.length} messages.`); - return ''; - } - - let oldestMesToDel = $('#chat').find(`.mes[mesid=${oldestMesIDToDel}]`); - - if (!oldestMesIDToDel && lastMesID > 0) { - oldestMesToDel = await loadUntilMesId(oldestMesIDToDel); - - if (!oldestMesToDel || !oldestMesToDel.length) { - return ''; - } - } - - let oldestDelMesCheckbox = $(oldestMesToDel).find('.del_checkbox'); - let newLastMesID = oldestMesIDToDel - 1; - console.debug(`DelMesReport -- numMesToDel: ${numMesToDel}, lastMesID: ${lastMesID}, oldestMesIDToDel:${oldestMesIDToDel}, newLastMesID: ${newLastMesID}`); - oldestDelMesCheckbox.trigger('click'); - let trueNumberOfDeletedMessage = lastMesID - oldestMesIDToDel + 1; - - //await delay(1) - $('#dialogue_del_mes_ok').trigger('click'); - toastr.success(`Deleted ${trueNumberOfDeletedMessage} messages.`); + // Just enter the delete mode. + if (!text) { + $('#option_delete_mes').trigger('click', { fromSlashCommand: true }); return ''; } - return ''; + const count = Number(text); + + // Nothing to delete. + if (count < 1) { + return ''; + } + + if (count > chat.length) { + toastr.warning(`Cannot delete more than ${chat.length} messages.`); + return ''; + } + + const range = `${chat.length - count}-${chat.length - 1}`; + return doMesCut(_, range); } function doResetPanels() { From b80ed958ae04135b0cd8c6380a17661b7c706106 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:26:49 +0300 Subject: [PATCH 11/20] Run summarize after QR execution --- public/scripts/extensions/memory/index.js | 2 +- public/scripts/extensions/quick-reply/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/scripts/extensions/memory/index.js b/public/scripts/extensions/memory/index.js index 2bb5c1269..0bc2ff577 100644 --- a/public/scripts/extensions/memory/index.js +++ b/public/scripts/extensions/memory/index.js @@ -914,7 +914,7 @@ jQuery(async function () { await addExtensionControls(); loadSettings(); - eventSource.on(event_types.MESSAGE_RECEIVED, onChatEvent); + eventSource.makeLast(event_types.CHARACTER_MESSAGE_RENDERED, onChatEvent); eventSource.on(event_types.MESSAGE_DELETED, onChatEvent); eventSource.on(event_types.MESSAGE_EDITED, onChatEvent); eventSource.on(event_types.MESSAGE_SWIPED, onChatEvent); diff --git a/public/scripts/extensions/quick-reply/index.js b/public/scripts/extensions/quick-reply/index.js index b0f496126..ab6044bf0 100644 --- a/public/scripts/extensions/quick-reply/index.js +++ b/public/scripts/extensions/quick-reply/index.js @@ -239,7 +239,7 @@ eventSource.on(event_types.CHAT_CHANGED, (...args)=>executeIfReadyElseQueue(onCh const onUserMessage = async () => { await autoExec.handleUser(); }; -eventSource.on(event_types.USER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onUserMessage, args)); +eventSource.makeFirst(event_types.USER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onUserMessage, args)); const onAiMessage = async (messageId) => { if (['...'].includes(chat[messageId]?.mes)) { @@ -249,7 +249,7 @@ const onAiMessage = async (messageId) => { await autoExec.handleAi(); }; -eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onAiMessage, args)); +eventSource.makeFirst(event_types.CHARACTER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onAiMessage, args)); const onGroupMemberDraft = async () => { await autoExec.handleGroupMemberDraft(); From 63a0ebb885698063a358b5ce0f66e1c0488128f2 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 11 Jul 2024 22:43:25 +0200 Subject: [PATCH 12/20] Move openai slash commands to init function --- public/script.js | 2 ++ public/scripts/openai.js | 33 +++++++++++++++++---------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/public/script.js b/public/script.js index f6cf2dba9..b6820e313 100644 --- a/public/script.js +++ b/public/script.js @@ -101,6 +101,7 @@ import { proxies, loadProxyPresets, selected_proxy, + initOpenai, } from './scripts/openai.js'; import { @@ -915,6 +916,7 @@ async function firstLoadInit() { initKeyboard(); initDynamicStyles(); initTags(); + initOpenai(); await getUserAvatars(true, user_avatar); await getCharacters(); await getBackgrounds(); diff --git a/public/scripts/openai.js b/public/scripts/openai.js index 00d319121..b30894f41 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -4679,22 +4679,23 @@ function runProxyCallback(_, value) { return foundName; } -SlashCommandParser.addCommandObject(SlashCommand.fromProps({ - name: 'proxy', - callback: runProxyCallback, - returns: 'current proxy', - namedArgumentList: [], - unnamedArgumentList: [ - SlashCommandArgument.fromProps({ - description: 'name', - typeList: [ARGUMENT_TYPE.STRING], - isRequired: true, - enumProvider: () => proxies.map(preset => new SlashCommandEnumValue(preset.name, preset.url)), - }), - ], - helpString: 'Sets a proxy preset by name.', -})); - +export function initOpenai() { + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ + name: 'proxy', + callback: runProxyCallback, + returns: 'current proxy', + namedArgumentList: [], + unnamedArgumentList: [ + SlashCommandArgument.fromProps({ + description: 'name', + typeList: [ARGUMENT_TYPE.STRING], + isRequired: true, + enumProvider: () => proxies.map(preset => new SlashCommandEnumValue(preset.name, preset.url)), + }), + ], + helpString: 'Sets a proxy preset by name.', + })); +} $(document).ready(async function () { $('#test_api_button').on('click', testApiConnection); From 8cbb80f44f38d2cc5cd7959d7736254e03210123 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 11 Jul 2024 22:43:56 +0200 Subject: [PATCH 13/20] Change 'world' enum provider query field, not UI --- .../scripts/slash-commands/SlashCommandCommonEnumsProvider.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js index 683f28ffa..6cc007156 100644 --- a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js +++ b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js @@ -3,6 +3,7 @@ import { extension_settings } from "../extensions.js"; import { getGroupMembers, groups, selected_group } from "../group-chats.js"; import { power_user } from "../power-user.js"; import { searchCharByName, getTagsList, tags } from "../tags.js"; +import { world_names } from '../world-info.js'; import { SlashCommandClosure } from "./SlashCommandClosure.js"; import { SlashCommandEnumValue, enumTypes } from "./SlashCommandEnumValue.js"; import { SlashCommandExecutor } from "./SlashCommandExecutor.js"; @@ -213,7 +214,7 @@ export const commonEnumProviders = { * * @returns {SlashCommandEnumValue[]} */ - worlds: () => $('#world_info').children().toArray().map(x => new SlashCommandEnumValue(x.textContent, null, enumTypes.name, enumIcons.world)), + worlds: () => world_names.map(worldName => new SlashCommandEnumValue(worldName, null, enumTypes.name, enumIcons.world)), /** * All existing injects for the current chat From 240f3f2c49089da9f4d65d0b8892c89ca9ef708e Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 11 Jul 2024 22:49:32 +0200 Subject: [PATCH 14/20] fix linting issues in enum providers --- .../SlashCommandCommonEnumsProvider.js | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js index 6cc007156..0d9aae5c6 100644 --- a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js +++ b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js @@ -1,12 +1,11 @@ -import { chat_metadata, characters, substituteParams, chat, extension_prompt_roles, extension_prompt_types } from "../../script.js"; -import { extension_settings } from "../extensions.js"; -import { getGroupMembers, groups, selected_group } from "../group-chats.js"; -import { power_user } from "../power-user.js"; -import { searchCharByName, getTagsList, tags } from "../tags.js"; +import { chat_metadata, characters, substituteParams, chat, extension_prompt_roles, extension_prompt_types } from '../../script.js'; +import { extension_settings } from '../extensions.js'; +import { getGroupMembers, groups } from '../group-chats.js'; +import { power_user } from '../power-user.js'; +import { searchCharByName, getTagsList, tags } from '../tags.js'; import { world_names } from '../world-info.js'; -import { SlashCommandClosure } from "./SlashCommandClosure.js"; -import { SlashCommandEnumValue, enumTypes } from "./SlashCommandEnumValue.js"; -import { SlashCommandExecutor } from "./SlashCommandExecutor.js"; +import { SlashCommandClosure } from './SlashCommandClosure.js'; +import { SlashCommandEnumValue, enumTypes } from './SlashCommandEnumValue.js'; /** * A collection of regularly used enum icons @@ -104,8 +103,8 @@ export const enumIcons = { // Remove possible nullable types definition to match type icon type = type.replace(/\?$/, ''); return enumIcons[type] ?? enumIcons.default; - } -} + }, +}; /** * A collection of common enum providers @@ -144,7 +143,7 @@ export const commonEnumProviders = { ...isAll || types.includes('global') ? Object.keys(extension_settings.variables.global ?? []).map(name => new SlashCommandEnumValue(name, null, enumTypes.macro, enumIcons.globalVariable)) : [], ...isAll || types.includes('local') ? Object.keys(chat_metadata.variables ?? []).map(name => new SlashCommandEnumValue(name, null, enumTypes.name, enumIcons.localVariable)) : [], ...isAll || types.includes('scope') ? [].map(name => new SlashCommandEnumValue(name, null, enumTypes.variable, enumIcons.scopeVariable)) : [], // TODO: Add scoped variables here, Lenny - ] + ]; }, /** @@ -181,7 +180,7 @@ export const commonEnumProviders = { * @param {('all' | 'existing' | 'not-existing')?} [mode='all'] - Which types of tags to show * @returns {() => SlashCommandEnumValue[]} */ - tagsForChar: (mode = 'all') => (/** @type {SlashCommandExecutor} */ executor) => { + tagsForChar: (mode = 'all') => (/** @type {import('./SlashCommandExecutor.js').SlashCommandExecutor} */ executor) => { // Try to see if we can find the char during execution to filter down the tags list some more. Otherwise take all tags. const charName = executor.namedArgumentList.find(it => it.name == 'name')?.value; if (charName instanceof SlashCommandClosure) throw new Error('Argument \'name\' does not support closures'); From f2089ed99443ecdc71a9fdfc52ac503782f8d927 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 11 Jul 2024 23:23:26 +0200 Subject: [PATCH 15/20] Linting in world-info.js --- public/scripts/world-info.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/public/scripts/world-info.js b/public/scripts/world-info.js index 355ac676b..e1638a2dd 100644 --- a/public/scripts/world-info.js +++ b/public/scripts/world-info.js @@ -14,7 +14,6 @@ import { SlashCommand } from './slash-commands/SlashCommand.js'; import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js'; import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; -import { SlashCommandExecutor } from './slash-commands/SlashCommandExecutor.js'; import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js'; @@ -1215,7 +1214,7 @@ function registerWorldInfoSlashCommands() { enumTypes.enum, enumIcons.getDataTypeIcon(value.type))), /** All existing UIDs based on the file argument as world name */ - wiUids: (/** @type {SlashCommandExecutor} */ executor) => { + wiUids: (/** @type {import('./slash-commands/SlashCommandExecutor.js'.SlashCommandExecutor)} */ executor) => { const file = executor.namedArgumentList.find(it => it.name == 'file')?.value; if (file instanceof SlashCommandClosure) throw new Error('Argument \'file\' does not support closures'); // Try find world from cache @@ -3161,7 +3160,8 @@ function duplicateWorldInfoEntry(data, uid) { } // Exclude uid and gather the rest of the properties - const { uid: _, ...originalData } = data.entries[uid]; + const originalData = Object.assign({}, data.entries[uid]); + delete originalData.uid; // Create new entry and copy over data const entry = createWorldInfoEntry(data.name, data); @@ -4326,8 +4326,9 @@ function onWorldInfoChange(args, text) { $('#world_info').val(null).trigger('change'); } } else { //if it's a pointer selection - let tempWorldInfo = []; - let selectedWorlds = $('#world_info').val().map((e) => Number(e)).filter((e) => !isNaN(e)); + const tempWorldInfo = []; + const val = $('#world_info').val(); + const selectedWorlds = (Array.isArray(val) ? val : [val]).map((e) => Number(e)).filter((e) => !isNaN(e)); if (selectedWorlds.length > 0) { selectedWorlds.forEach((worldIndex) => { const existingWorldName = world_names[worldIndex]; From f53fa0d19da20fd98ed5c8f7aaf1ce8ad343b86f Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Fri, 12 Jul 2024 01:09:46 +0300 Subject: [PATCH 16/20] Add missing await --- public/scripts/preset-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/preset-manager.js b/public/scripts/preset-manager.js index 19c3f0bbd..756c518ef 100644 --- a/public/scripts/preset-manager.js +++ b/public/scripts/preset-manager.js @@ -166,7 +166,7 @@ class PresetManager { async savePresetAs() { const inputValue = this.getSelectedPresetName(); const popupText = !this.isNonGenericApi() ? '

Hint: Use a character/group name to bind preset to a specific chat.

' : ''; - const name = Popup.show.input('Preset name:', popupText, inputValue); + const name = await Popup.show.input('Preset name:', popupText, inputValue); if (!name) { console.log('Preset name not provided'); return; From f74c212945a8cf25a03d0945841e57b8d20997b5 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Fri, 12 Jul 2024 01:12:25 +0300 Subject: [PATCH 17/20] Fix popup type --- public/scripts/preset-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/preset-manager.js b/public/scripts/preset-manager.js index 756c518ef..5d25140dc 100644 --- a/public/scripts/preset-manager.js +++ b/public/scripts/preset-manager.js @@ -594,7 +594,7 @@ export async function initPresetManager() { return; } - const confirm = await Popup.show.input('Delete the preset?', 'This action is irreversible and your current settings will be overwritten.'); + const confirm = await Popup.show.confirm('Delete the preset?', 'This action is irreversible and your current settings will be overwritten.'); if (!confirm) { return; } From c90a25e0cddc64f69bf7939860252c77970405af Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Fri, 12 Jul 2024 01:19:34 +0300 Subject: [PATCH 18/20] Fix import syntax --- public/scripts/world-info.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/world-info.js b/public/scripts/world-info.js index e1638a2dd..d497e8020 100644 --- a/public/scripts/world-info.js +++ b/public/scripts/world-info.js @@ -1214,7 +1214,7 @@ function registerWorldInfoSlashCommands() { enumTypes.enum, enumIcons.getDataTypeIcon(value.type))), /** All existing UIDs based on the file argument as world name */ - wiUids: (/** @type {import('./slash-commands/SlashCommandExecutor.js'.SlashCommandExecutor)} */ executor) => { + wiUids: (/** @type {import('./slash-commands/SlashCommandExecutor.js').SlashCommandExecutor} */ executor) => { const file = executor.namedArgumentList.find(it => it.name == 'file')?.value; if (file instanceof SlashCommandClosure) throw new Error('Argument \'file\' does not support closures'); // Try find world from cache From 4c7e5fbd60ede50eb097254f67cf2c4fb9ce2091 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 12 Jul 2024 00:29:16 +0200 Subject: [PATCH 19/20] Allow popup buttons returning 'null' for cancelled --- public/scripts/popup.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/public/scripts/popup.js b/public/scripts/popup.js index 944af3ae7..4ece1b468 100644 --- a/public/scripts/popup.js +++ b/public/scripts/popup.js @@ -194,7 +194,7 @@ export class Popup { const buttonElement = document.createElement('div'); buttonElement.classList.add('menu_button', 'popup-button-custom', 'result-control'); buttonElement.classList.add(...(button.classes ?? [])); - buttonElement.dataset.result = String(button.result ?? undefined); + buttonElement.dataset.result = String(button.result); // This is expected to also write 'null' or 'staging', to indicate cancel and no action respectively buttonElement.textContent = button.text; buttonElement.dataset.i18n = buttonElement.textContent; buttonElement.tabIndex = 0; @@ -317,9 +317,14 @@ export class Popup { // Bind event listeners for all result controls to their defined event type this.dlg.querySelectorAll('[data-result]').forEach(resultControl => { if (!(resultControl instanceof HTMLElement)) return; - const result = Number(resultControl.dataset.result); - if (String(undefined) === String(resultControl.dataset.result)) return; - if (isNaN(result)) throw new Error('Invalid result control. Result must be a number. ' + resultControl.dataset.result); + // If no value was set, we exit out and don't bind an action + if (String(resultControl.dataset.result) === String(undefined)) return; + + // Make sure that both `POPUP_RESULT` numbers and also `null` as 'cancelled' are supported + const result = String(resultControl.dataset.result) === String(null) ? null + : Number(resultControl.dataset.result); + + if (result !== null && isNaN(result)) throw new Error('Invalid result control. Result must be a number. ' + resultControl.dataset.result); const type = resultControl.dataset.resultEvent || 'click'; resultControl.addEventListener(type, async () => await this.complete(result)); }); From a57d9949133f039aa31839ba41d8c037da16f4c9 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Fri, 12 Jul 2024 07:29:42 +0000 Subject: [PATCH 20/20] Calculate new height after setting min height --- public/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/script.js b/public/script.js index b6820e313..13ece6069 100644 --- a/public/script.js +++ b/public/script.js @@ -9236,9 +9236,9 @@ jQuery(async function () { function autoFitEditTextArea(e) { const computedStyle = window.getComputedStyle(e); const maxHeight = parseInt(computedStyle.maxHeight, 10); - const newHeight = e.scrollHeight + 4; scroll_holder = chatElement[0].scrollTop; e.style.height = computedStyle.minHeight; + const newHeight = e.scrollHeight + 4; e.style.height = (newHeight < maxHeight) ? `${newHeight}px` : `${maxHeight}px`; is_use_scroll_holder = true; }