diff --git a/public/script.js b/public/script.js index 001cc72fc..e04a308f8 100644 --- a/public/script.js +++ b/public/script.js @@ -174,7 +174,7 @@ import { saveBase64AsFile, uuidv4, } from './scripts/utils.js'; -import { debounce_timeout } from './scripts/constants.js'; +import { debounce_timeout, IGNORE_SYMBOL } from './scripts/constants.js'; import { doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js'; import { COMMENT_NAME_DEFAULT, executeSlashCommandsOnChatInput, getSlashCommandsHelp, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, processChatSlashCommands, stopScriptExecution } from './scripts/slash-commands.js'; @@ -5301,6 +5301,12 @@ function formatMessageHistoryItem(chatItem, isInstruct, forceOutputSequence) { const itemName = chatItem.is_user ? chatItem['name'] : characterName; const shouldPrependName = !isNarratorType; + // If this symbol flag is set, completely ignore the message. + // This can be used to hide messages without affecting the number of messages in the chat. + if (chatItem.extra?.[IGNORE_SYMBOL]) { + return ''; + } + // Don't include a name if it's empty let textResult = chatItem?.name && shouldPrependName ? `${itemName}: ${chatItem.mes}\n` : `${chatItem.mes}\n`; diff --git a/public/scripts/constants.js b/public/scripts/constants.js index f95a8e146..5cd1a2ff5 100644 --- a/public/scripts/constants.js +++ b/public/scripts/constants.js @@ -14,3 +14,11 @@ export const debounce_timeout = { /** [5 sec] For delayed tasks, like auto-saving or completing batch operations that need a significant pause. */ extended: 5000, }; + +/** + * Used as an ephemeral key in message extra metadata. + * When set, the message will be excluded from generation + * prompts without affecting the number of chat messages, + * which is needed to preserve world info timed effects. + */ +export const IGNORE_SYMBOL = Symbol.for('ignore'); diff --git a/public/scripts/openai.js b/public/scripts/openai.js index b0c23d3eb..775fad33a 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -75,6 +75,7 @@ import { Popup, POPUP_RESULT } from './popup.js'; import { t } from './i18n.js'; import { ToolManager } from './tool-calling.js'; import { accountStorage } from './util/AccountStorage.js'; +import { IGNORE_SYMBOL } from './constants.js'; export { openai_messages_count, @@ -523,6 +524,13 @@ function setOpenAIMessages(chat) { let role = chat[j]['is_user'] ? 'user' : 'assistant'; let content = chat[j]['mes']; + // If this symbol flag is set, completely ignore the message. + // This can be used to hide messages without affecting the number of messages in the chat. + if (chat[j].extra?.[IGNORE_SYMBOL]) { + j++; + continue; + } + // 100% legal way to send a message as system if (chat[j].extra?.type === system_message_types.NARRATOR) { role = 'system'; diff --git a/public/scripts/st-context.js b/public/scripts/st-context.js index ae32ff3f8..0ba1104bd 100644 --- a/public/scripts/st-context.js +++ b/public/scripts/st-context.js @@ -83,6 +83,7 @@ import { convertCharacterBook, getWorldInfoPrompt, loadWorldInfo, reloadEditor, import { ChatCompletionService, TextCompletionService } from './custom-request.js'; import { ConnectionManagerRequestService } from './extensions/shared.js'; import { updateReasoningUI, parseReasoningFromString } from './reasoning.js'; +import { IGNORE_SYMBOL } from './constants.js'; export function getContext() { return { @@ -225,6 +226,9 @@ export function getContext() { parseReasoningFromString, unshallowCharacter, unshallowGroupMembers, + symbols: { + ignore: IGNORE_SYMBOL, + }, }; }