Adjust itemized prompts on message move/delete (#5000) * Adjust itemized prompts on message move/delete * Sort itemized prompts on swap * Remove itemized prompt on regeneration

684b755826a80d86ce9c65beb9dda1ced64563c8

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

Signed
2 files changed, +51 -2Showing whitespace changes
public/script.js+8 -1
@@ -272,7 +272,7 @@ import { extractReasoningFromData, extractReasoningSignatureFromData, initReason
272272import { accountStorage } from './scripts/util/AccountStorage.js';
273273import { initWelcomeScreen, openPermanentAssistantChat, openPermanentAssistantCard, getPermanentAssistantAvatar } from './scripts/welcome-screen.js';
274274import { initDataMaid } from './scripts/data-maid.js';
275275import { clearItemizedPrompts, deleteItemizedPromptForMessage, deleteItemizedPrompts, findItemizedPromptSet, initItemizedPrompts, itemizedParams, itemizedPrompts, loadItemizedPrompts, promptItemize, replaceItemizedPromptText, saveItemizedPrompts, swapItemizedPrompts } from './scripts/itemized-prompts.js';
276276import { getSystemMessageByType, initSystemMessages, SAFETY_CHAT, sendSystemMessage, system_message_types, system_messages } from './scripts/system-messages.js';
277277import { event_types, eventSource } from './scripts/events.js';
278278import { initAccessibility } from './scripts/a11y.js';
@@ -1546,6 +1546,7 @@ export async function clearChat() {
15461546}
15471547
15481548export async function deleteLastMessage() {
1549+ deleteItemizedPromptForMessage(chat.length - 1);
15491550 chat.length = chat.length - 1;
15501551 chatElement.children('.mes').last().remove();
15511552 await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);
@@ -1601,6 +1602,7 @@ export async function deleteMessage(id, swipeDeletionIndex = undefined, askConfi
16011602 chat_metadata.tainted = true;
16021603
16031604 const startIndex = [0, minId].includes(id) ? id : null;
1605+ deleteItemizedPromptForMessage(id);
16041606 updateViewMessageIds(startIndex);
16051607 saveChatDebounced();
16061608
@@ -4230,6 +4232,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
42304232 //do nothing? why does this check exist?
42314233 }
42324234 else if (type !== 'quiet' && type !== 'swipe' && !isImpersonate && !dryRun && chat.length) {
4235+ deleteItemizedPromptForMessage(chat.length - 1);
42334236 chat.length = chat.length - 1;
42344237 await removeLastMessage();
42354238 await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);
@@ -8142,6 +8145,7 @@ async function messageEditMove(sourceId, targetId) {
81428145 this_edit_mes_id = targetId;
81438146 }
81448147
8148+ swapItemizedPrompts(sourceId, targetId);
81458149 updateViewMessageIds();
81468150 refreshSwipeButtons();
81478151 await saveChatConditional();
@@ -11450,6 +11454,9 @@ jQuery(async function () {
1145011454 });
1145111455
1145211456 if (this_del_mes >= 0) {
11457+ for (let i = (chat.length - 1); i >= this_del_mes; i--) {
11458+ deleteItemizedPromptForMessage(i);
11459+ }
1145311460 chatElement.find(`.mes[mesid="${this_del_mes}"]`).nextAll('div').remove();
1145411461 chatElement.find(`.mes[mesid="${this_del_mes}"]`).remove();
1145511462 chat.length = this_del_mes;
public/scripts/itemized-prompts.js+43 -1
@@ -222,6 +222,7 @@ export async function itemizedParams(itemizedPrompts, thisPromptSet, incomingMes
222222
223223export function findItemizedPromptSet(itemizedPrompts, incomingMesId) {
224224 let thisPromptSet = undefined;
225+ priorPromptArrayItemForRawPromptDisplay = -1;
225226
226227 for (let i = 0; i < itemizedPrompts.length; i++) {
227228 console.log(`looking for ${incomingMesId} vs ${itemizedPrompts[i].mesId}`);
@@ -262,7 +263,7 @@ export async function promptItemize(itemizedPrompts, requestedMesId) {
262263
263264 /** @type {HTMLElement} */
264265 const diffPrevPrompt = popup.dlg.querySelector('#diffPrevPrompt');
265266 if (priorPromptArrayItemForRawPromptDisplay >= 0) {
266267 diffPrevPrompt.style.display = '';
267268 diffPrevPrompt.addEventListener('click', function () {
268269 const dmp = new DiffMatchPatch();
@@ -350,3 +351,44 @@ export function initItemizedPrompts() {
350351 await deleteItemizedPrompts(name);
351352 });
352353}
354+
355+/**
356+ * Swaps the itemized prompts between two messages. Useful when moving messages around in the chat.
357+ * @param {number} sourceMessageId Source message ID
358+ * @param {number} targetMessageId Target message ID
359+ */
360+export function swapItemizedPrompts(sourceMessageId, targetMessageId) {
361+ if (!Array.isArray(itemizedPrompts)) {
362+ return;
363+ }
364+
365+ const sourcePrompts = itemizedPrompts.filter(x => x.mesId === sourceMessageId);
366+ const targetPrompts = itemizedPrompts.filter(x => x.mesId === targetMessageId);
367+
368+ sourcePrompts.forEach(prompt => {
369+ prompt.mesId = targetMessageId;
370+ });
371+
372+ targetPrompts.forEach(prompt => {
373+ prompt.mesId = sourceMessageId;
374+ });
375+
376+ itemizedPrompts.sort((a, b) => a.mesId - b.mesId);
377+}
378+
379+/**
380+ * Deletes the itemized prompt for a specific message.
381+ * Shifts down other itemized prompts as necessary.
382+ * @param {number} messageId Message ID to delete itemized prompt for
383+ */
384+export function deleteItemizedPromptForMessage(messageId) {
385+ if (!Array.isArray(itemizedPrompts)) {
386+ return;
387+ }
388+
389+ itemizedPrompts = itemizedPrompts.filter(x => x.mesId !== messageId);
390+
391+ for (const prompt of itemizedPrompts.filter(x => x.mesId > messageId)) {
392+ prompt.mesId -= 1;
393+ }
394+}