diff --git a/public/script.js b/public/script.js
index 506d0681f..8ad914990 100644
--- a/public/script.js
+++ b/public/script.js
@@ -84,6 +84,7 @@ import {
} from "./scripts/poe.js";
import { debounce, delay } from "./scripts/utils.js";
+import { extension_settings, loadExtensionSettings } from "./scripts/extensions.js";
//exporting functions and vars for mods
export {
@@ -2396,6 +2397,7 @@ async function getSettings(type) {
script.src = src;
$("body").append(script);
}
+ loadExtensionSettings(settings);
}
//get the character to auto-load
@@ -2449,6 +2451,7 @@ async function saveSettings(type) {
horde_settings: horde_settings,
power_user: power_user,
poe_settings: poe_settings,
+ extension_settings: extension_settings,
...nai_settings,
...kai_settings,
...oai_settings,
diff --git a/public/scripts/extensions.js b/public/scripts/extensions.js
index 6a5b17b92..47daef84e 100644
--- a/public/scripts/extensions.js
+++ b/public/scripts/extensions.js
@@ -1,33 +1,65 @@
-import { callPopup } from "../script.js";
+import { callPopup, saveSettings, saveSettingsDebounced } from "../script.js";
import { isSubsetOf } from "./utils.js";
export {
getContext,
getApiUrl,
+ loadExtensionSettings,
defaultRequestArgs,
modules,
+ extension_settings,
};
const extensionNames = ['caption', 'dice', 'expressions', 'floating-prompt', 'memory'];
const manifests = await getManifests(extensionNames);
-const extensions_urlKey = 'extensions_url';
-const extensions_autoConnectKey = 'extensions_autoconnect';
-const extensions_disabledKey = 'extensions_disabled';
+
+// TODO: Delete in next release
+function migrateFromLocalStorage() {
+ const extensions_urlKey = 'extensions_url';
+ const extensions_autoConnectKey = 'extensions_autoconnect';
+ const extensions_disabledKey = 'extensions_disabled';
+
+ const apiUrl = localStorage.getItem(extensions_urlKey);
+ const autoConnect = localStorage.getItem(extensions_autoConnectKey);
+ const extensionsDisabled = localStorage.getItem(extensions_disabledKey);
+
+ if (apiUrl !== null) {
+ extension_settings.apiUrl = apiUrl;
+ localStorage.removeItem(extensions_urlKey);
+ }
+
+ if (autoConnect !== null) {
+ extension_settings.autoConnect = autoConnect;
+ localStorage.removeItem(extensions_autoConnectKey);
+ }
+
+ if (extensionsDisabled !== null) {
+ extension_settings.disabledExtensions = JSON.parse(extensionsDisabled);
+ localStorage.removeItem(extensions_disabledKey);
+ }
+}
+
+const extension_settings = {
+ apiUrl: '',
+ autoConnect: '',
+ disabledExtensions: [],
+ memory: {},
+ note: {
+ default: '',
+ },
+ caption: {},
+ expressions: {},
+ dice: {},
+};
let modules = [];
-let disabledExtensions = getDisabledExtensions();
let activeExtensions = new Set();
const getContext = () => window['TavernAI'].getContext();
-const getApiUrl = () => localStorage.getItem('extensions_url');
+const getApiUrl = () => extension_settings.apiUrl;
const defaultUrl = "http://localhost:5100";
const defaultRequestArgs = { method: 'GET', headers: { 'Bypass-Tunnel-Reminder': 'bypass' } };
let connectedToApi = false;
-function getDisabledExtensions() {
- const value = localStorage.getItem(extensions_disabledKey);
- return value ? JSON.parse(value) : [];
-}
-
function onDisableExtensionClick() {
const name = $(this).data('name');
disableExtension(name);
@@ -38,15 +70,15 @@ function onEnableExtensionClick() {
enableExtension(name);
}
-function enableExtension(name) {
- disabledExtensions = disabledExtensions.filter(x => x !== name);
- localStorage.setItem(extensions_disabledKey, JSON.stringify(disabledExtensions));
+async function enableExtension(name) {
+ extension_settings.disabledExtensions = extension_settings.disabledExtensions.filter(x => x !== name);
+ await saveSettings();
location.reload();
}
-function disableExtension(name) {
- disabledExtensions.push(name);
- localStorage.setItem(extensions_disabledKey, JSON.stringify(disabledExtensions));
+async function disableExtension(name) {
+ extension_settings.disabledExtensions.push(name);
+ await saveSettings();
location.reload();
}
@@ -77,7 +109,7 @@ async function activateExtensions() {
// all required modules are active (offline extensions require none)
if (isSubsetOf(modules, manifest.requires)) {
try {
- const isDisabled = disabledExtensions.includes(name);
+ const isDisabled = extension_settings.disabledExtensions.includes(name);
const li = document.createElement('li');
if (!isDisabled) {
@@ -104,20 +136,27 @@ async function activateExtensions() {
async function connectClickHandler() {
const baseUrl = $("#extensions_url").val();
- localStorage.setItem(extensions_urlKey, baseUrl);
+ extension_settings.apiUrl = baseUrl;
+ saveSettingsDebounced();
await connectToApi(baseUrl);
}
function autoConnectInputHandler() {
const value = $(this).prop('checked');
- localStorage.setItem(extensions_autoConnectKey, value.toString());
+ extension_settings.autoConnect = !!value;
if (value && !connectedToApi) {
$("#extensions_connect").trigger('click');
}
+
+ saveSettingsDebounced();
}
async function connectToApi(baseUrl) {
+ if (!baseUrl) {
+ return;
+ }
+
const url = new URL(baseUrl);
url.pathname = '/api/modules';
@@ -220,7 +259,7 @@ function showExtensionsDetails() {
}
}
}
- else if (disabledExtensions.includes(name)) {
+ else if (extension_settings.disabledExtensions.includes(name)) {
html += `
Extension is disabled. Enable
`;
}
else {
@@ -234,17 +273,24 @@ function showExtensionsDetails() {
callPopup(`${html}
`, 'text');
}
-$(document).ready(async function () {
- const url = localStorage.getItem(extensions_urlKey) ?? defaultUrl;
- const autoConnect = localStorage.getItem(extensions_autoConnectKey) == 'true';
- $("#extensions_url").val(url);
- $("#extensions_connect").on('click', connectClickHandler);
- $("#extensions_autoconnect").on('input', autoConnectInputHandler);
- $("#extensions_autoconnect").prop('checked', autoConnect).trigger('input');
- $("#extensions_details").on('click', showExtensionsDetails);
- $(document).on('click', '.disable_extension', onDisableExtensionClick);
- $(document).on('click', '.enable_extension', onEnableExtensionClick);
+function loadExtensionSettings(settings) {
+ migrateFromLocalStorage();
+
+ if (settings.extension_settings) {
+ Object.assign(extension_settings, settings.extension_settings);
+ }
+
+ $("#extensions_url").val(extension_settings.apiUrl);
+ $("#extensions_autoconnect").prop('checked', extension_settings.autoConnect).trigger('input');
// Activate offline extensions
activateExtensions();
+}
+
+$(document).ready(async function () {
+ $("#extensions_connect").on('click', connectClickHandler);
+ $("#extensions_autoconnect").on('input', autoConnectInputHandler);
+ $("#extensions_details").on('click', showExtensionsDetails);
+ $(document).on('click', '.disable_extension', onDisableExtensionClick);
+ $(document).on('click', '.enable_extension', onEnableExtensionClick);
});
\ No newline at end of file
diff --git a/public/scripts/extensions/floating-prompt/index.js b/public/scripts/extensions/floating-prompt/index.js
index a9c1d8f38..c14b0c959 100644
--- a/public/scripts/extensions/floating-prompt/index.js
+++ b/public/scripts/extensions/floating-prompt/index.js
@@ -1,46 +1,57 @@
-import { getContext } from "../../extensions.js";
+import { chat_metadata, saveSettingsDebounced } from "../../../script.js";
+import { extension_settings, getContext } from "../../extensions.js";
+import { debounce } from "../../utils.js";
export { MODULE_NAME };
+const saveChatDebounced = debounce(async () => await getContext().saveChat(), 1000);
+
const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory
const UPDATE_INTERVAL = 1000;
-let lastMessageNumber = null;
-let promptInsertionInterval = 1;
-let promptInsertionPosition = 1;
-let promptInsertionDepth = 0;
-let defaultNote = '';
+const DEFAULT_DEPTH = 4;
+const DEFAULT_POSITION = 1;
+const DEFAULT_INTERVAL = 1;
-function onExtensionFloatingPromptInput() {
- saveSettings();
+const metadata_keys = {
+ prompt: 'note_prompt',
+ interval: 'note_interval',
+ depth: 'note_depth',
+ position: 'note_position',
}
-function onExtensionFloatingIntervalInput() {
- promptInsertionInterval = Number($(this).val());
- saveSettings();
+async function onExtensionFloatingPromptInput() {
+ chat_metadata[metadata_keys.prompt] = $(this).val();
+ saveChatDebounced();
}
-function onExtensionFloatingDepthInput() {
+async function onExtensionFloatingIntervalInput() {
+ chat_metadata[metadata_keys.interval] = Number($(this).val());
+ saveChatDebounced();
+}
+
+async function onExtensionFloatingDepthInput() {
let value = Number($(this).val());
- if (promptInsertionDepth < 0) {
+ if (value < 0) {
value = Math.abs(value);
$(this).val(value);
}
- promptInsertionDepth = value;
- saveSettings();
+ chat_metadata[metadata_keys.depth] = value;
+ saveChatDebounced();
}
-function onExtensionFloatingPositionInput(e) {
- promptInsertionPosition = e.target.value;
- saveSettings();
+async function onExtensionFloatingPositionInput(e) {
+ chat_metadata[metadata_keys.position] = e.target.value;
+ saveChatDebounced();
}
function onExtensionFloatingDefaultInput() {
- defaultNote = $(this).val();
- saveSettings();
+ extension_settings.note.default = $(this).val();
+ saveSettingsDebounced();
}
+// TODO Remove in next release
function getLocalStorageKeys() {
const context = getContext();
@@ -65,27 +76,60 @@ function getLocalStorageKeys() {
};
}
-function loadSettings() {
+function migrateFromLocalStorage() {
const keys = getLocalStorageKeys();
- defaultNote = localStorage.getItem(keys.default) ?? '';
- const prompt = localStorage.getItem(keys.prompt) ?? defaultNote ?? '';
- const interval = localStorage.getItem(keys.interval) ?? 1;
- const position = localStorage.getItem(keys.position) ?? 1;
- const depth = localStorage.getItem(keys.depth) ?? 0;
- $('#extension_floating_prompt').val(prompt).trigger('input');
- $('#extension_floating_interval').val(interval).trigger('input');
- $('#extension_floating_depth').val(depth).trigger('input');
- $(`input[name="extension_floating_position"][value="${position}"]`).prop('checked', true).trigger('change');
- $('#extension_floating_default').val(defaultNote);
+ const defaultNote = localStorage.getItem(keys.default);
+ const prompt = localStorage.getItem(keys.prompt);
+ const interval = localStorage.getItem(keys.interval);
+ const position = localStorage.getItem(keys.position);
+ const depth = localStorage.getItem(keys.depth);
+
+ if (defaultNote !== null) {
+ if (typeof extension_settings.note !== 'object') {
+ extension_settings.note = {};
+ }
+
+ extension_settings.note.default = defaultNote;
+ saveSettingsDebounced();
+ localStorage.removeItem(keys.default);
+ }
+
+ if (chat_metadata) {
+ if (interval !== null) {
+ chat_metadata[metadata_keys.interval] = interval;
+ localStorage.removeItem(keys.interval);
+ }
+
+ if (depth !== null) {
+ chat_metadata[metadata_keys.depth] = depth;
+ localStorage.removeItem(keys.depth);
+ }
+
+ if (position !== null) {
+ chat_metadata[metadata_keys.position] = position;
+ localStorage.removeItem(keys.position);
+ }
+
+ if (prompt !== null) {
+ chat_metadata[metadata_keys.prompt] = prompt;
+ localStorage.removeItem(keys.prompt);
+ saveChatDebounced();
+ }
+ }
}
-function saveSettings() {
- const keys = getLocalStorageKeys();
- localStorage.setItem(keys.prompt, $('#extension_floating_prompt').val());
- localStorage.setItem(keys.interval, $('#extension_floating_interval').val());
- localStorage.setItem(keys.depth, $('#extension_floating_depth').val());
- localStorage.setItem(keys.position, $('input:radio[name="extension_floating_position"]:checked').val());
- localStorage.setItem(keys.default, defaultNote);
+
+function loadSettings() {
+ migrateFromLocalStorage();
+ chat_metadata[metadata_keys.prompt] = chat_metadata[metadata_keys.prompt] ?? extension_settings.note.default ?? '';
+ chat_metadata[metadata_keys.interval] = chat_metadata[metadata_keys.interval] ?? DEFAULT_INTERVAL;
+ chat_metadata[metadata_keys.position] = chat_metadata[metadata_keys.position] ?? DEFAULT_POSITION;
+ chat_metadata[metadata_keys.depth] = chat_metadata[metadata_keys.depth] ?? DEFAULT_DEPTH;
+ $('#extension_floating_prompt').val(chat_metadata[metadata_keys.prompt]);
+ $('#extension_floating_interval').val(chat_metadata[metadata_keys.interval]);
+ $('#extension_floating_depth').val(chat_metadata[metadata_keys.depth]);
+ $(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true);
+ $('#extension_floating_default').val(extension_settings.note.default);
}
async function moduleWorker() {
@@ -98,24 +142,24 @@ async function moduleWorker() {
loadSettings();
// take the count of messages
- lastMessageNumber = Array.isArray(context.chat) && context.chat.length ? context.chat.filter(m => m.is_user).length : 0;
+ let lastMessageNumber = Array.isArray(context.chat) && context.chat.length ? context.chat.filter(m => m.is_user).length : 0;
// special case for new chat
if (Array.isArray(context.chat) && context.chat.length === 1) {
lastMessageNumber = 1;
}
- if (lastMessageNumber <= 0 || promptInsertionInterval <= 0) {
+ if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) {
$('#extension_floating_counter').text('No');
return;
}
- const messagesTillInsertion = lastMessageNumber >= promptInsertionInterval
- ? (lastMessageNumber % promptInsertionInterval)
- : (promptInsertionInterval - lastMessageNumber);
+ const messagesTillInsertion = lastMessageNumber >= chat_metadata[metadata_keys.interval]
+ ? (lastMessageNumber % chat_metadata[metadata_keys.interval])
+ : (chat_metadata[metadata_keys.interval] - lastMessageNumber);
const shouldAddPrompt = messagesTillInsertion == 0;
const prompt = shouldAddPrompt ? $('#extension_floating_prompt').val() : '';
- context.setExtensionPrompt(MODULE_NAME, prompt, promptInsertionPosition, promptInsertionDepth);
+ context.setExtensionPrompt(MODULE_NAME, prompt, chat_metadata[metadata_keys.position], chat_metadata[metadata_keys.depth]);
$('#extension_floating_counter').text(shouldAddPrompt ? 'This' : messagesTillInsertion);
}