diff --git a/package-lock.json b/package-lock.json index 816f02cd6..4432b27af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sillytavern", - "version": "1.8.2", + "version": "1.8.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sillytavern", - "version": "1.8.2", + "version": "1.8.3", "license": "AGPL-3.0", "dependencies": { "@dqbd/tiktoken": "^1.0.2", diff --git a/package.json b/package.json index 729706985..0c310b2f8 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "type": "git", "url": "https://github.com/SillyTavern/SillyTavern.git" }, - "version": "1.8.2", + "version": "1.8.3", "scripts": { "start": "node server.js", "pkg": "pkg --compress Gzip --no-bytecode --public ." diff --git a/public/index.html b/public/index.html index 78c44207f..a8969f3a9 100644 --- a/public/index.html +++ b/public/index.html @@ -2373,6 +2373,9 @@ + @@ -2816,7 +2819,7 @@
-
+

@@ -3297,7 +3300,12 @@ +
+
+
+ + @@ -3616,4 +3624,4 @@ - + \ No newline at end of file diff --git a/public/script.js b/public/script.js index 90ae9de90..84c02c9e8 100644 --- a/public/script.js +++ b/public/script.js @@ -757,7 +757,6 @@ $.get("/csrf-token").then(async (data) => { function checkOnlineStatus() { ///////// REMOVED LINES THAT DUPLICATE RA_CHeckOnlineStatus FEATURES - if (online_status == "no_connection") { $("#online_status_indicator2").css("background-color", "red"); //Kobold $("#online_status_text2").html("No connection..."); @@ -1137,10 +1136,7 @@ function messageFormatting(mes, ch_name, isSystem, isUser) { mes = mes.replaceAll(substituteParams(power_user.user_prompt_bias), ""); } - const regexResult = getRegexedString(mes, regex_placement.MD_DISPLAY); - if (regexResult) { - mes = regexResult; - } + mes = getRegexedString(mes, regex_placement.MD_DISPLAY); if (power_user.auto_fix_generated_markdown) { mes = fixMarkdown(mes); @@ -2957,10 +2953,7 @@ export function replaceBiasMarkup(str) { } export async function sendMessageAsUser(textareaText, messageBias) { - const regexResult = getRegexedString(textareaText, regex_placement.USER_INPUT); - if (regexResult) { - textareaText = regexResult; - } + textareaText = getRegexedString(textareaText, regex_placement.USER_INPUT); chat[chat.length] = {}; chat[chat.length - 1]['name'] = name1; @@ -3561,10 +3554,7 @@ function cleanUpMessage(getMessage, isImpersonate, displayIncompleteSentences = } // Regex uses vars, so add before formatting - const regexResult = getRegexedString(getMessage, isImpersonate ? regex_placement.USER_INPUT : regex_placement.AI_OUTPUT); - if (regexResult) { - getMessage = regexResult; - } + getMessage = getRegexedString(getMessage, isImpersonate ? regex_placement.USER_INPUT : regex_placement.AI_OUTPUT); if (!displayIncompleteSentences && power_user.trim_sentences) { getMessage = end_trim_to_sentence(getMessage, power_user.include_newline); @@ -4995,16 +4985,13 @@ function updateMessage(div) { regexPlacement = regex_placement.SYSTEM; } - const regexResult = getRegexedString( + text = getRegexedString( text, regexPlacement, { characterOverride: regexPlacement === regex_placement.SENDAS ? mes.name : undefined } ); - if (regexResult) { - text = regexResult; - } if (power_user.trim_spaces) { text = text.trim(); @@ -6123,10 +6110,7 @@ async function createOrEditCharacter(e) { ) { // MARK - kingbri: Regex on character greeting message // May need to be placed somewhere else - const regexResult = getRegexedString(this_ch_mes, regex_placement.AI_OUTPUT); - if (regexResult) { - this_ch_mes = regexResult; - } + this_ch_mes = getRegexedString(this_ch_mes, regex_placement.AI_OUTPUT); clearChat(); chat.length = 0; @@ -6504,7 +6488,12 @@ const swipe_right = () => { } export function updateCharacterCount(characterSelector) { - const visibleCharacters = $(characterSelector).filter(":visible"); + const visibleCharacters = $(characterSelector) + .not(".hiddenBySearch") + .not(".hiddenByTag") + .not(".hiddenByGroup") + .not(".hiddenByGroupMember") + .not(".hiddenByFav"); const visibleCharacterCount = visibleCharacters.length; const totalCharacterCount = $(characterSelector).length; @@ -7840,9 +7829,11 @@ $(document).ready(function () { $(document).on("click", ".mes_edit_delete", async function () { - const confirmation = await callPopup("Are you sure you want to delete this message?", 'confirm'); - if (!confirmation) { - return; + if (power_user.confirm_message_delete) { + const confirmation = await callPopup("Are you sure you want to delete this message?", 'confirm'); + if (!confirmation) { + return; + } } const mes = $(this).closest(".mes"); diff --git a/public/scripts/extensions/expressions/index.js b/public/scripts/extensions/expressions/index.js index bf560ba09..9b8b1b091 100644 --- a/public/scripts/extensions/expressions/index.js +++ b/public/scripts/extensions/expressions/index.js @@ -152,7 +152,7 @@ async function visualNovelSetCharacterSprites(container, name, expression) { const path = currentSpritePath || defaultSpritePath || ''; const img = expressionImage.find('img'); - setImage(img, path); + await setImage(img, path); } expressionImage.toggleClass('hidden', noSprites); } else { @@ -163,7 +163,7 @@ async function visualNovelSetCharacterSprites(container, name, expression) { $('#visual-novel-wrapper').append(template); dragElement($(template[0])); template.toggleClass('hidden', noSprites); - setImage(template.find('img'), defaultSpritePath || ''); + await setImage(template.find('img'), defaultSpritePath || ''); const fadeInPromise = new Promise(resolve => { template.fadeIn(250, () => resolve()); }); @@ -284,7 +284,9 @@ async function setLastMessageSprite(img, avatar, labels) { } } -function setImage(img, path) { +async function setImage(img, path) { + // Cohee: If something goes wrong, uncomment this to return to the old behavior + /* img.attr('src', path); img.removeClass('default'); img.off('error'); @@ -293,6 +295,66 @@ function setImage(img, path) { $(this).off('error'); $(this).attr('src', ''); }); + */ + + return new Promise(resolve => { + const prevExpressionSrc = img.attr('src'); + const expressionClone = img.clone(); + const originalId = img.attr('id'); + + //only swap expressions when necessary + if (prevExpressionSrc !== path && !img.hasClass('expression-animating')) { + //clone expression + expressionClone.addClass('expression-clone') + //make invisible and remove id to prevent double ids + //must be made invisible to start because they share the same Z-index + expressionClone.attr('id', '').css({ opacity: 0 }); + //add new sprite path to clone src + expressionClone.attr('src', path); + //add invisible clone to html + expressionClone.appendTo(img.parent()); + + const duration = 200; + + //add animation flags to both images + //to prevent multiple expression changes happening simultaneously + img.addClass('expression-animating') + //position absolute prevent the original from jumping around during transition + img.css('position', 'absolute') + expressionClone.addClass('expression-animating') + //fade the clone in + expressionClone.css({ + opacity: 0 + }).animate({ + opacity: 1 + }, duration) + //when finshed fading in clone, fade out the original + .promise().done(function () { + img.animate({ + opacity: 0 + }, duration); + //remove old expression + img.remove(); + //replace ID so it becomes the new 'original' expression for next change + expressionClone.attr('id', originalId); + expressionClone.removeClass('expression-animating'); + resolve(); + }); + + expressionClone.removeClass('expression-clone'); + + expressionClone.removeClass('default'); + expressionClone.off('error'); + expressionClone.on('error', function () { + console.debug('Expression image error', sprite.path); + $(this).attr('src', ''); + $(this).off('error'); + resolve(); + }); + } else { + resolve(); + } + }); } function onExpressionsShowDefaultInput() { @@ -620,6 +682,8 @@ async function setExpression(character, expression, force) { console.debug('entered setExpressions'); await validateImages(character); const img = $('img.expression'); + const prevExpressionSrc = img.attr('src'); + const expressionClone = img.clone() const sprite = (spriteCache[character] && spriteCache[character].find(x => x.label === expression)); console.debug('checking for expression images to show..'); @@ -638,26 +702,67 @@ async function setExpression(character, expression, force) { } if (groupMember.name == character) { - setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path); + await setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path); return; } } } + //only swap expressions when necessary + if (prevExpressionSrc !== sprite.path + && !img.hasClass('expression-animating')) { + //clone expression + expressionClone.addClass('expression-clone') + //make invisible and remove id to prevent double ids + //must be made invisible to start because they share the same Z-index + expressionClone.attr('id', '').css({ opacity: 0 }); + //add new sprite path to clone src + expressionClone.attr('src', sprite.path); + //add invisible clone to html + expressionClone.appendTo($("#expression-holder")) - img.attr('src', sprite.path); - img.removeClass('default'); - img.off('error'); - img.on('error', function () { - console.debug('Expression image error', sprite.path); - $(this).attr('src', ''); - $(this).off('error'); - if (force && extension_settings.expressions.showDefault) { + const duration = 200; + + //add animation flags to both images + //to prevent multiple expression changes happening simultaneously + img.addClass('expression-animating') + //position absolute prevent the original from jumping around during transition + img.css('position', 'absolute') + expressionClone.addClass('expression-animating') + //fade the clone in + expressionClone.css({ + opacity: 0 + }).animate({ + opacity: 1 + }, duration) + //when finshed fading in clone, fade out the original + .promise().done(function () { + img.animate({ + opacity: 0 + }, duration); + //remove old expression + img.remove(); + //replace ID so it becomes the new 'original' expression for next change + expressionClone.attr('id', 'expression-image') + expressionClone.removeClass('expression-animating') + }); + + + expressionClone.removeClass('expression-clone'); + + expressionClone.removeClass('default'); + expressionClone.off('error'); + expressionClone.on('error', function () { + console.debug('Expression image error', sprite.path); + $(this).attr('src', ''); + $(this).off('error'); + if (force && extension_settings.expressions.showDefault) { + setDefault(); + } + }); + } else { + if (extension_settings.expressions.showDefault) { setDefault(); } - }); - } else { - if (extension_settings.expressions.showDefault) { - setDefault(); } } @@ -665,8 +770,8 @@ async function setExpression(character, expression, force) { console.debug('setting default'); const defImgUrl = `/img/default-expressions/${expression}.png`; //console.log(defImgUrl); - img.attr('src', defImgUrl); - img.addClass('default'); + expressionClone.attr('src', defImgUrl); + expressionClone.addClass('default'); } document.getElementById("expression-holder").style.display = ''; } diff --git a/public/scripts/extensions/expressions/style.css b/public/scripts/extensions/expressions/style.css index 7494f3e9e..ef16fa4db 100644 --- a/public/scripts/extensions/expressions/style.css +++ b/public/scripts/extensions/expressions/style.css @@ -20,6 +20,9 @@ #visual-novel-wrapper .expression-holder { width: max-content; + display: flex; + left: unset; + right: unset; } #visual-novel-wrapper .hidden { @@ -31,21 +34,6 @@ object-fit: cover; }*/ -/* .expression-holder { - min-width: 100px; - min-height: 100px; - max-height: 90vh; - max-width: 90vh; - width: calc((100vw - var(--sheldWidth)) /2); - position: absolute; - padding: 0; - filter: drop-shadow(2px 2px 2px #51515199); - z-index: 29; - overflow: hidden; - display: none; - bottom: 0; -} */ - .expression-holder { min-width: 100px; min-height: 100px; @@ -55,6 +43,7 @@ position: absolute; bottom: 0; padding: 0; + left: 0; filter: drop-shadow(2px 2px 2px #51515199); z-index: 2; overflow: hidden; @@ -62,8 +51,13 @@ } img.expression { + min-width: 100px; + min-height: 100px; + max-height: 90vh; + max-width: 90vh; width: 100%; - height: 100%; + bottom: 0; + padding: 0; vertical-align: bottom; object-fit: contain; } @@ -79,6 +73,10 @@ img.expression.default { margin-top: 50px; } +.expression-clone { + position: absolute; +} + .debug-image { display: none; visibility: collapse; diff --git a/public/scripts/extensions/infinity-context/index.js b/public/scripts/extensions/infinity-context/index.js index f079c5827..f00f266dc 100644 --- a/public/scripts/extensions/infinity-context/index.js +++ b/public/scripts/extensions/infinity-context/index.js @@ -133,20 +133,7 @@ async function loadSettings() { function onStrategyChange() { console.debug('changing chromadb strat'); extension_settings.chromadb.strategy = $('#chromadb_strategy').val(); - - $('#chromadb_custom_depth').hide(); - $('label[for="chromadb_custom_depth"]').hide(); - $('#chromadb_custom_msg').hide(); - $('label[for="chromadb_custom_msg"]').hide(); - - $('#chromadb_hhaa_wrapperfmt').hide(); - $('label[for="chromadb_hhaa_wrapperfmt"]').hide(); - $('#chromadb_hhaa_memoryfmt').hide(); - $('label[for="chromadb_hhaa_memoryfmt"]').hide(); - $('#chromadb_hhaa_token_limit').hide(); - $('label[for="chromadb_hhaa_token_limit"]').hide(); - - if(extension_settings.chromadb.strategy === "custom"){ + if (extension_settings.chromadb.strategy === "custom") { $('#chromadb_custom_depth').show(); $('label[for="chromadb_custom_depth"]').show(); $('#chromadb_custom_msg').show(); @@ -226,6 +213,16 @@ function onFileSplitLengthInput() { saveSettingsDebounced(); } +function onChunkNLInput() { + let shouldSplit = $('#onChunkNLInput').is(':checked'); + if (shouldSplit) { + extension_settings.chromadb.file_split_type = "newline"; + } else { + extension_settings.chromadb.file_split_type = "length"; + } + saveSettingsDebounced(); +} + function checkChatId(chat_id) { if (!chat_id || chat_id.trim() === '') { toastr.error('Please select a character and try again.'); @@ -450,7 +447,7 @@ async function queryMultiMessages(chat_id, query) { const context = getContext(); const response = await fetch("/getallchatsofcharacter", { method: 'POST', - body: JSON.stringify({ avatar_url: context.characters[context.characterId].avatar}), + body: JSON.stringify({ avatar_url: context.characters[context.characterId].avatar }), headers: getRequestHeaders(), }); if (!response.ok) { @@ -492,8 +489,14 @@ async function onSelectInjectFile(e) { try { toastr.info('This may take some time, depending on the file size', 'Processing...'); const text = await getFileText(file); - - const split = splitRecursive(text, extension_settings.chromadb.file_split_length).filter(onlyUnique); + extension_settings.chromadb.file_split_type = "newline"; + //allow splitting on newlines or splitrecursively + let split = []; + if (extension_settings.chromadb.file_split_type == "newline") { + split = text.split(/\r?\n/).filter(onlyUnique); + } else { + split = splitRecursive(text, extension_settings.chromadb.file_split_length).filter(onlyUnique); + } const baseDate = Date.now(); const messages = split.map((m, i) => ({ @@ -590,6 +593,9 @@ window.chromadb_interceptGeneration = async (chat, maxContext) => { if (!currentChatId) return; + //log the current settings + console.debug("CHROMADB: Current settings: %o", extension_settings.chromadb); + const selectedStrategy = extension_settings.chromadb.strategy; const recallStrategy = extension_settings.chromadb.recall_strategy; let recallMsg = extension_settings.chromadb.recall_msg || defaultSettings.chroma_default_msg; @@ -599,6 +605,10 @@ window.chromadb_interceptGeneration = async (chat, maxContext) => { const messagesToStore = chat.slice(0, -extension_settings.chromadb.keep_context); if (messagesToStore.length > 0 && !extension_settings.chromadb.freeze) { + //log the messages to store + console.debug("CHROMADB: Messages to store: %o", messagesToStore); + //log the messages to store length vs keep context + console.debug("CHROMADB: Messages to store length vs keep context: %o vs %o", messagesToStore.length, extension_settings.chromadb.keep_context); await addMessages(currentChatId, messagesToStore); } @@ -618,18 +628,18 @@ window.chromadb_interceptGeneration = async (chat, maxContext) => { } console.log("ChromDB Query text:", queryBlob); - if (recallStrategy === 'multichat'){ + if (recallStrategy === 'multichat') { console.log("Utilizing multichat") queriedMessages = await queryMultiMessages(currentChatId, queryBlob); } - else{ + else { queriedMessages = await queryMessages(currentChatId, queryBlob); } - if(chromaSortStrategy === "date"){ + if (chromaSortStrategy === "date") { queriedMessages.sort((a, b) => a.date - b.date); } - else{ + else { queriedMessages.sort((a, b) => b.distance - a.distance); } console.log(queriedMessages); @@ -727,10 +737,10 @@ window.chromadb_interceptGeneration = async (chat, maxContext) => { let chatset = new Set(chat.map(obj => obj.mes)); newChat = newChat.filter(obj => !chatset.has(obj.mes)); - if(chromaDepth === -1){ + if(chromaDepth === -1) { chat.splice(chat.length, 0, ...newChat); } - else{ + else { chat.splice(chromaDepth, 0, ...newChat); } } @@ -741,7 +751,6 @@ window.chromadb_interceptGeneration = async (chat, maxContext) => { chat.splice(0, messagesToStore.length, ...newChat); } - console.log('ChromaDB chat after injection', chat); } } @@ -837,6 +846,10 @@ jQuery(async () => { Use % strategy +