diff --git a/extensions/expressions/index.js b/extensions/expressions/index.js new file mode 100644 index 0000000..6a33c96 --- /dev/null +++ b/extensions/expressions/index.js @@ -0,0 +1,101 @@ +const MODULE_NAME = 'expressions'; +const SETTINGS_KEY = 'extensions_memory_settings'; +const UPDATE_INTERVAL = 1000; + +let lastCharacter = null; +let lastMessage = null; +let inApiCall = false; + +const getContext = function () { + return window['TavernAI'].getContext(); +} + +const getApiUrl = function () { + return localStorage.getItem('extensions_url'); +} + +async function moduleWorker() { + function getLastCharacterMessage() { + const reversedChat = context.chat.slice().reverse(); + + for (let mes of reversedChat) { + if (mes.is_user || mes.is_system) { + continue; + } + + return mes.mes; + } + + return ''; + } + + const context = getContext(); + + // group chats and non-characters not supported + if (context.groupId || !context.characterId) { + removeExpression(); + return; + } + + // character changed + if (lastCharacter !== context.characterId) { + removeExpression(); + } + + // check if last message changed + const currentLastMessage = getLastCharacterMessage(); + if (lastCharacter === context.characterId && lastMessage === currentLastMessage) { + return; + } + + // API is busy + if (inApiCall) { + return; + } + + try { + inApiCall = true; + const url = new URL(getApiUrl()); + url.pathname = '/api/classify'; + + const apiResult = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: currentLastMessage }) + }); + + if (apiResult.ok) { + const data = await apiResult.json(); + const expression = data.classification[0].label; + setExpression(context.name2, expression); + } + + } + catch (error) { + console.log(error); + } + finally { + inApiCall = false; + lastCharacter = context.characterId; + lastMessage = currentLastMessage; + } +} + +function removeExpression() { + $('div.expression').css('background-image', 'unset'); +} + +function setExpression(character, expression) { + const imgUrl = `url('/characters/${character}/${expression}.png')`; + $('div.expression').css('background-image', imgUrl); +} + +(function () { + function addExpressionImage() { + const html = `
` + $('body').append(html); + } + + addExpressionImage(); + setInterval(moduleWorker, UPDATE_INTERVAL); +})(); \ No newline at end of file diff --git a/extensions/expressions/manifest.json b/extensions/expressions/manifest.json new file mode 100644 index 0000000..33b8e24 --- /dev/null +++ b/extensions/expressions/manifest.json @@ -0,0 +1,8 @@ +{ + "display_name": "Character Expressions", + "requires": [ + "classify" + ], + "js": "index.js", + "css": "style.css" +} \ No newline at end of file diff --git a/extensions/expressions/style.css b/extensions/expressions/style.css new file mode 100644 index 0000000..b4394a7 --- /dev/null +++ b/extensions/expressions/style.css @@ -0,0 +1,19 @@ +div.expression { + background-image: unset; + background-repeat: no-repeat; + background-size: contain; + width: 200px; + height: 300px; + position: fixed; + left: 0; + bottom: 0; + margin-left: 10px; + filter: drop-shadow(2px 2px 4px #cccccc84); + transition: 500ms; +} + +@media screen and (max-width:1200px) { + div.expression { + display: none; + } +} \ No newline at end of file diff --git a/extensions/memory/index.js b/extensions/memory/index.js index d7c5384..0ea988c 100644 --- a/extensions/memory/index.js +++ b/extensions/memory/index.js @@ -135,7 +135,7 @@ async function moduleWorker() { && chat[chat.length - 1].extra.memory && lastMessageId === chat.length && getStringHash(chat[chat.length - 1].mes) !== lastMessageHash) { - chat[chat.length - 1].extra.memory = null; + delete chat[chat.length - 1].extra.memory; } try { @@ -228,7 +228,19 @@ async function summarizeChat(context) { } function onMemoryRestoreClick() { + const context = getContext(); + const content = $('#memory_contents').val(); + const reversedChat = context.chat.slice().reverse(); + for (let mes of reversedChat) { + if (mes.extra && mes.extra.memory == content) { + delete mes.extra.memory; + break; + } + } + + const newContent = getLatestMemoryFromChat(context.chat); + setMemoryContext(newContent, false); } function onMemoryContentInput() {