diff --git a/public/script.js b/public/script.js index e3a1fad3d..fd13ea4d7 100644 --- a/public/script.js +++ b/public/script.js @@ -1612,6 +1612,9 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, message_already_generated = `${magName}: `; } + // To trim after multigen ended + const magFirst = message_already_generated; + const interruptedByCommand = processCommands($("#send_textarea").val(), type); if (interruptedByCommand) { @@ -1638,6 +1641,14 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, hideSwipeButtons(); } + // Set empty promise resolution functions + if (typeof resolve !== 'function') { + resolve = () => { }; + } + if (typeof reject !== 'function') { + reject = () => { }; + } + if (selected_group && !is_group_generating) { generateGroupWrapper(false, type, { resolve, reject, quiet_prompt, force_chid }); return; @@ -2350,23 +2361,6 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, hideSwipeButtons(); let getMessage = await streamingProcessor.generate(); - // Cohee: Basically a dead-end code... (disabled by isStreamingEnabled) - // I wasn't able to get multigen working with real streaming - // consistently without screwing the interim prompting - if (isMultigenEnabled()) { - tokens_already_generated += this_amount_gen; // add new gen amt to any prev gen counter.. - message_already_generated += getMessage; - promptBias = ''; - if (!streamingProcessor.isStopped && shouldContinueMultigen(getMessage, isImpersonate)) { - streamingProcessor.isFinished = false; - runGenerate(getMessage); - console.log('returning to make generate again'); - return; - } - - getMessage = message_already_generated; - } - if (streamingProcessor && !streamingProcessor.isStopped && streamingProcessor.isFinished) { streamingProcessor.onFinishStreaming(streamingProcessor.messageId, getMessage); streamingProcessor = null; @@ -2414,7 +2408,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, return; } - getMessage = message_already_generated; + getMessage = message_already_generated.substring(magFirst.length); } //Formating @@ -2473,13 +2467,14 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, showSwipeButtons(); setGenerationProgress(0); $('.mes_buttons:last').show(); + + if (type !== 'quiet') { + resolve(); + } }; function onError(jqXHR, exception) { - if (type == 'quiet') { - reject(exception); - } - + reject(exception); $("#send_textarea").removeAttr('disabled'); is_send_press = false; activateSendButtons(); @@ -3093,6 +3088,10 @@ function saveReply(type, getMessage, this_mes_is_name, title) { const item = chat[chat.length - 1]; if (item['swipe_id'] !== undefined) { item['swipes'][item['swipes'].length - 1] = item['mes']; + } else { + item['swipe_id'] = 0; + item['swipes'] = []; + item['swipes'][0] = chat[chat.length - 1]['mes']; } return { type, getMessage }; diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index d5b7de039..171908216 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -46,6 +46,7 @@ import { menu_type, select_selected_character, cancelTtsPlay, + isMultigenEnabled, } from "../script.js"; import { appendTagToList, createTagMapFromList, getTagsList, applyTagsOnCharacterSelect } from './tags.js'; @@ -426,7 +427,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { let lastMessageText = lastMessage.mes; let activationText = ""; let isUserInput = false; - let isQuietGenDone = false; + let isGenerationDone = false; if (userInput && userInput.length && !by_auto_mode) { isUserInput = true; @@ -438,6 +439,23 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { } } + const resolveOriginal = params.resolve; + const rejectOriginal = params.reject; + + if (typeof params.resolve === 'function') { + params.resolve = function () { + isGenerationDone = true; + resolveOriginal.apply(this, arguments); + }; + } + + if (typeof params.reject === 'function') { + params.reject = function () { + isGenerationDone = true; + rejectOriginal.apply(this, arguments); + } + } + const activationStrategy = Number(group.activation_strategy ?? group_activation_strategy.NATURAL); let activatedMembers = []; @@ -450,16 +468,6 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { activatedMembers = activateListOrder(group.members.slice(0, 1)); } - const resolveOriginal = params.resolve; - const rejectOriginal = params.reject; - params.resolve = function () { - isQuietGenDone = true; - resolveOriginal.apply(this, arguments); - }; - params.reject = function () { - isQuietGenDone = true; - rejectOriginal.apply(this, arguments); - } } else if (type === "swipe") { activatedMembers = activateSwipe(group.members); @@ -482,13 +490,14 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { // now the real generation begins: cycle through every character for (const chId of activatedMembers) { + isGenerationDone = false; const generateType = type == "swipe" || type == "impersonate" || type == "quiet" ? type : "group_chat"; setCharacterId(chId); setCharacterName(characters[chId].name) await Generate(generateType, { automatic_trigger: by_auto_mode, ...(params || {}) }); - if (type !== "swipe" && type !== "impersonate") { + if (type !== "swipe" && type !== "impersonate" && !isMultigenEnabled()) { // update indicator and scroll down typingIndicator .find(".typing_indicator_name") @@ -499,9 +508,10 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { }); } + // TODO: This is awful. Refactor this while (true) { // if not swipe - check if message generated already - if (type !== "swipe" && chat.length == messagesBefore) { + if (type !== "swipe" && !isMultigenEnabled() && chat.length == messagesBefore) { await delay(100); } // if swipe - see if message changed @@ -514,6 +524,13 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { break; } } + else if (isMultigenEnabled()) { + if (isGenerationDone) { + break; + } else { + await delay(100); + } + } else { if (lastMessageText === chat[chat.length - 1].mes) { await delay(100); @@ -532,6 +549,13 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { break; } } + else if (isMultigenEnabled()) { + if (isGenerationDone) { + break; + } else { + await delay(100); + } + } else { if (!$("#send_textarea").val() || $("#send_textarea").val() == userInput) { await delay(100); @@ -542,7 +566,15 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { } } else if (type === 'quiet') { - if (isQuietGenDone) { + if (isGenerationDone) { + break; + } else { + await delay(100); + } + } + else if (isMultigenEnabled()) { + if (isGenerationDone) { + messagesBefore++; break; } else { await delay(100); diff --git a/readme.md b/readme.md index 093341471..2a4b3ac3b 100644 --- a/readme.md +++ b/readme.md @@ -168,45 +168,58 @@ In order to enable viewing your keys by clicking a button in the API block: ## Remote connections -Most often this is for people who want to use SillyTavern on their mobile phones while at home. -If you want to enable other devices to connect to your TAI server, open 'config.conf' in a text editor, and change: +Most often this is for people who want to use SillyTavern on their mobile phones while their PC runs the ST server on the same wifi network. -``` -const whitelistMode = true; -``` +However, it can be used to allow remote connections from anywhere as well. -to +**IMPORTANT: SillyTavern is a single-user program, so anyone who logs in will be able to see all characters and chats, and be able to change any settings inside the UI.** -``` -const whitelistMode = false; -``` +### 1. Managing whitelisted IPs -Save the file. -Restart your TAI server. - -You will now be able to connect from other devices. - -### Managing whitelisted IPs - -You can add or remove whitelisted IPs by editing the `whitelist` array in `config.conf`. You can also provide a `whitelist.txt` file in the same directory as `config.conf` with one IP address per line like: +* Create a new text file inside your SillyTavern base install folder called `whitelist.txt`. +* Open the file in a text editor, add a list of IPs you want to be allowed to connect. +*IP ranges are not accepted. Each IP must be listed individually like this:* ```txt 192.168.0.1 192.168.0.2 +192.168.0.3 +192.168.0.4 ``` +* Save the `whitelist.txt` file. +* Restart your TAI server. -The `whitelist` array in `config.conf` will be ignored if `whitelist.txt` exists. +Now devices which have the IP specified in the file will be able to connect. -***Disclaimer: Anyone else who knows your IP address and TAI port number will be able to connect as well*** +*Note: `config.conf` also has a `whitelist` array, which you can use in the same way, but this array will be ignored if `whitelist.txt` exists.* -To connect over wifi you'll need your PC's local wifi IP address +### 2. Connecting to ST from a remote device -* (For Windows: windows button > type 'cmd.exe' in the search bar> type 'ipconfig' in the console, hit Enter > "IPv4" listing) -if you want other people on the internet to connect, check [here](https://whatismyipaddress.com/) for 'IPv4' +After the whitelist has been setup, to connect over wifi you'll need the IP of the ST-hosting device. + +If the ST-hosting device is on the same wifi network, you will point your remote device's browser to the ST-host's internal wifi IP: + +* For Windows: windows button > type `cmd.exe` in the search bar > type `ipconfig` in the console, hit Enter > look for `IPv4` listing. + +If you (or someone else) wants to connect to your hosted ST while not being on the same network, you will need the public IP of your ST-hosting device. + +While using the ST-hosting device, access [this page](https://whatismyipaddress.com/) and look for for `IPv4`. This is what you would use to connect from the remote device. + +### Opening your ST to all IPs + +We do not reccomend doing this, but you can open `config.conf` and change `whitelist` to `false`. + +You must remove (or rename) `whitelist.txt` in the SillyTavern base install folder, if it exists. + +This is usually an insecure practice, so we require you to set a username and password when you do this. + +The username and password are set in `config.conf`. + +After restarting your ST server, any device will be able to connect to it, regardless of their IP as long as they know the username and password. ### Still Unable To Connect? -- Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for portforwarding on your router, otherwise someone could find your chat logs and that's a big no-no. +* Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for portforwarding on your router, otherwise someone could find your chat logs and that's a big no-no. * Enable the Private Network profile type in Settings > Network and Internet > Ethernet. This is VERY important for Windows 11, otherwise you would be unable to connect even with the aforementioned firewall rules. ## Performance issues?