Merge pull request #3561 from SillyTavern/fix-syncing-swipe-data Fix syncing swipe data on reasoning parse & utility function to sync swipe data

7b55d91d35e9de0b74624abca8899c1851337b4d

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +60 -15Ignore whitespace
public/script.js+53 -11
@@ -6086,17 +6086,52 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes,
60866086 return { type, getMessage };
60876087}
60886088
6089-export function syncCurrentSwipeInfoExtras() {
6089+/**
6090+ * Syncs the current message and all its data into the swipe data at the given message ID (or the last message if no ID is given).
6091+ *
6092+ * If the swipe data is invalid in some way, this function will exit out without doing anything.
6093+ * @param {number?} [messageId=null] - The ID of the message to sync with the swipe data. If no ID is given, the last message is used.
6094+ * @returns {boolean} Whether the message was successfully synced
6095+ */
6096+export function syncMesToSwipe(messageId = null) {
60906097 if (!chat.length) {
60916098 return false;
60926099 }
6093- const currentMessage = chat[chat.length - 1];
6100+
6094- if (currentMessage && Array.isArray(currentMessage.swipe_info) && typeof currentMessage.swipe_id === 'number') {
6101+ const targetMessageId = messageId ?? chat.length - 1;
6095- const swipeInfo = currentMessage.swipe_info[currentMessage.swipe_id];
6102+ if (chat.length > targetMessageId || targetMessageId < 0) {
6096- if (swipeInfo && typeof swipeInfo === 'object') {
6103+ console.warn(`[syncMesToSwipe] Invalid message ID: ${messageId}`);
6097- swipeInfo.extra = structuredClone(currentMessage.extra);
6104+ return false;
60986105 }
6106+
6107+ const targetMessage = chat[targetMessageId];
6108+
6109+ // No swipe data there yet, exit out
6110+ if (typeof targetMessage.swipe_id !== 'number') {
6111+ return false;
60996112 }
6113+ // If swipes structure is invalid, exit out (for now?)
6114+ if (!Array.isArray(targetMessage.swipe_info) || !Array.isArray(targetMessage.swipes)) {
6115+ return false;
6116+ }
6117+ // If the swipe is not present yet, exit out (will likely be copied later)
6118+ if (!targetMessage.swipes[targetMessage.swipe_id] || !targetMessage.swipe_info[targetMessage.swipe_id]) {
6119+ return false;
6120+ }
6121+
6122+ const targetSwipeInfo = targetMessage.swipe_info[targetMessage.swipe_id];
6123+ if (typeof targetSwipeInfo !== 'object') {
6124+ return false;
6125+ }
6126+
6127+ targetMessage.swipes[targetMessage.swipe_id] = targetMessage.mes;
6128+
6129+ targetSwipeInfo.send_date = targetMessage.send_date;
6130+ targetSwipeInfo.gen_started = targetMessage.gen_started;
6131+ targetSwipeInfo.gen_finished = targetMessage.gen_finished;
6132+ targetSwipeInfo.extra = structuredClone(targetMessage.extra);
6133+
6134+ return true;
61006135}
61016136
61026137function saveImageToMessage(img, mes) {
@@ -6401,6 +6436,7 @@ export function saveChatDebounced() {
64016436 if (chatSaveTimeout) {
64026437 console.debug('Clearing chat save timeout');
64036438 clearTimeout(chatSaveTimeout);
6439+ chatSaveTimeout = null;
64046440 }
64056441
64066442 chatSaveTimeout = setTimeout(async () => {
@@ -6417,7 +6453,7 @@ export function saveChatDebounced() {
64176453 console.debug('Chat save timeout triggered');
64186454 await saveChatConditional();
64196455 console.debug('Chat saved');
64206456 }, 1000DEFAULT_SAVE_EDIT_TIMEOUT);
64216457}
64226458
64236459export async function saveChat(chatName, withMetadata, mesId) {
@@ -8032,6 +8068,12 @@ export async function saveChatConditional() {
80328068 }
80338069
80348070 try {
8071+ if (chatSaveTimeout) {
8072+ console.debug('Debounced chat save canceled');
8073+ clearTimeout(chatSaveTimeout);
8074+ chatSaveTimeout = null;
8075+ }
8076+
80358077 isChatSaving = true;
80368078
80378079 if (selected_group) {
@@ -8568,7 +8610,7 @@ function swipe_left() { // when we swipe left..but no generation.
85688610 }
85698611
85708612 // Make sure ad-hoc changes to extras are saved before swiping away
85718613 syncCurrentSwipeInfoExtrassyncMesToSwipe();
85728614
85738615 const swipe_duration = 120;
85748616 const swipe_range = '700px';
@@ -8706,7 +8748,7 @@ const swipe_right = () => {
87068748 }
87078749
87088750 // Make sure ad-hoc changes to extras are saved before swiping away
87098751 syncCurrentSwipeInfoExtrassyncMesToSwipe();
87108752
87118753 const swipe_duration = 200;
87128754 const swipe_range = 700;
public/scripts/reasoning.js+5 -2
@@ -1,7 +1,7 @@
11import {
22 moment,
33} from '../lib.js';
44import { chat, closeMessageEditor, event_types, eventSource, main_api, messageFormatting, saveChatConditional, saveChatDebounced, saveSettingsDebounced, substituteParams, syncMesToSwipe, updateMessageBlock } from '../script.js';
55import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
66import { getCurrentLocale, t, translate } from './i18n.js';
77import { MacrosParser } from './macros.js';
@@ -1046,8 +1046,11 @@ function registerReasoningAppEvents() {
10461046 message.mes = parsedReasoning.content;
10471047 }
10481048
1049- // Find if a message already exists in DOM and must be updated
10501049 if (contentUpdated) {
1050+ syncMesToSwipe();
1051+ saveChatDebounced();
1052+
1053+ // Find if a message already exists in DOM and must be updated
10511054 const messageRendered = document.querySelector(`.mes[mesid="${idx}"]`) !== null;
10521055 if (messageRendered) {
10531056 console.debug('[Reasoning] Updating message block', idx);
public/scripts/slash-commands.js+2 -2
@@ -42,7 +42,7 @@ import {
4242 showMoreMessages,
4343 stopGeneration,
4444 substituteParams,
4545 syncCurrentSwipeInfoExtrassyncMesToSwipe,
4646 system_avatar,
4747 system_message_types,
4848 this_chid,
@@ -2921,7 +2921,7 @@ async function addSwipeCallback(args, value) {
29212921
29222922 if (isTrueBoolean(args.switch)) {
29232923 // Make sure ad-hoc changes to extras are saved before swiping away
29242924 syncCurrentSwipeInfoExtrassyncMesToSwipe();
29252925 lastMessage.swipe_id = newSwipeId;
29262926 lastMessage.mes = lastMessage.swipes[newSwipeId];
29272927 lastMessage.extra = structuredClone(lastMessage.swipe_info?.[newSwipeId]?.extra ?? lastMessage.extra ?? {});