add missing args to some slash commands

This commit is contained in:
SrJuggernaut 2023-12-06 19:26:29 -06:00
parent 55d7bd6a87
commit d6d0371459

View File

@ -1,52 +1,50 @@
import { import {
Generate,
activateSendButtons,
addOneMessage, addOneMessage,
callPopup,
characters, characters,
chat, chat,
chat_metadata, chat_metadata,
comment_avatar,
deactivateSendButtons,
default_avatar, default_avatar,
eventSource, eventSource,
event_types, event_types,
extension_prompt_types,
extractMessageBias, extractMessageBias,
generateQuietPrompt,
generateRaw,
getThumbnailUrl, getThumbnailUrl,
is_send_press,
main_api,
name1,
reloadCurrentChat,
replaceBiasMarkup, replaceBiasMarkup,
saveChatConditional, saveChatConditional,
sendMessageAsUser,
sendSystemMessage, sendSystemMessage,
setCharacterId,
setCharacterName,
setExtensionPrompt,
setUserName, setUserName,
substituteParams, substituteParams,
comment_avatar,
system_avatar, system_avatar,
system_message_types, system_message_types,
setCharacterId,
generateQuietPrompt,
reloadCurrentChat,
sendMessageAsUser,
name1,
Generate,
this_chid, this_chid,
setCharacterName,
generateRaw,
callPopup,
deactivateSendButtons,
activateSendButtons,
main_api,
is_send_press,
extension_prompt_types,
setExtensionPrompt,
} from '../script.js'; } from '../script.js';
import { getMessageTimeStamp } from './RossAscends-mods.js'; import { getMessageTimeStamp } from './RossAscends-mods.js';
import { findGroupMemberId, groups, is_group_generating, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js';
import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';
import { autoSelectPersona } from './personas.js';
import { getContext, saveMetadataDebounced } from './extensions.js';
import { hideChatMessage, unhideChatMessage } from './chats.js'; import { hideChatMessage, unhideChatMessage } from './chats.js';
import { getContext, saveMetadataDebounced } from './extensions.js';
import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
import { findGroupMemberId, groups, is_group_generating, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js';
import { autoSelectPersona } from './personas.js';
import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';
import { decodeTextTokens, getFriendlyTokenizerName, getTextTokens, getTokenCount } from './tokenizers.js';
import { delay, isFalseBoolean, isTrueBoolean, stringToRange, trimToEndSentence, trimToStartSentence, waitUntilCondition } from './utils.js'; import { delay, isFalseBoolean, isTrueBoolean, stringToRange, trimToEndSentence, trimToStartSentence, waitUntilCondition } from './utils.js';
import { registerVariableCommands, resolveVariable } from './variables.js'; import { registerVariableCommands, resolveVariable } from './variables.js';
import { decodeTextTokens, getFriendlyTokenizerName, getTextTokens, getTokenCount } from './tokenizers.js';
export { export {
executeSlashCommands, executeSlashCommands, getSlashCommandsHelp, registerSlashCommand,
registerSlashCommand,
getSlashCommandsHelp,
}; };
class SlashCommandParser { class SlashCommandParser {
@ -55,18 +53,18 @@ class SlashCommandParser {
this.helpStrings = {}; this.helpStrings = {};
} }
addCommand(command, callback, aliases, helpString = '', interruptsGeneration = false, purgeFromMessage = true) { addCommand (command, callback, aliases, helpString = '', interruptsGeneration = false, purgeFromMessage = true) {
const fnObj = { callback, helpString, interruptsGeneration, purgeFromMessage }; const fnObj = { callback, helpString, interruptsGeneration, purgeFromMessage };
if ([command, ...aliases].some(x => Object.hasOwn(this.commands, x))) { if ([ command, ...aliases ].some(x => Object.hasOwn(this.commands, x))) {
console.trace('WARN: Duplicate slash command registered!'); console.trace('WARN: Duplicate slash command registered!');
} }
this.commands[command] = fnObj; this.commands[ command ] = fnObj;
if (Array.isArray(aliases)) { if (Array.isArray(aliases)) {
aliases.forEach((alias) => { aliases.forEach((alias) => {
this.commands[alias] = fnObj; this.commands[ alias ] = fnObj;
}); });
} }
@ -75,11 +73,11 @@ class SlashCommandParser {
let aliasesString = `(alias: ${aliases.map(x => `<span class="monospace">/${x}</span>`).join(', ')})`; let aliasesString = `(alias: ${aliases.map(x => `<span class="monospace">/${x}</span>`).join(', ')})`;
stringBuilder += aliasesString; stringBuilder += aliasesString;
} }
this.helpStrings[command] = stringBuilder; this.helpStrings[ command ] = stringBuilder;
} }
parse(text) { parse (text) {
const excludedFromRegex = ['sendas']; const excludedFromRegex = [ 'sendas' ];
const firstSpace = text.indexOf(' '); const firstSpace = text.indexOf(' ');
const command = firstSpace !== -1 ? text.substring(1, firstSpace) : text.substring(1); const command = firstSpace !== -1 ? text.substring(1, firstSpace) : text.substring(1);
const args = firstSpace !== -1 ? text.substring(firstSpace + 1) : ''; const args = firstSpace !== -1 ? text.substring(firstSpace + 1) : '';
@ -91,17 +89,17 @@ class SlashCommandParser {
const namedArgPattern = /(\w+)=("(?:\\.|[^"\\])*"|\S+)/g; const namedArgPattern = /(\w+)=("(?:\\.|[^"\\])*"|\S+)/g;
let match; let match;
while ((match = namedArgPattern.exec(args)) !== null) { while ((match = namedArgPattern.exec(args)) !== null) {
const key = match[1]; const key = match[ 1 ];
const value = match[2]; const value = match[ 2 ];
// Remove the quotes around the value, if any // Remove the quotes around the value, if any
argObj[key] = value.replace(/(^")|("$)/g, ''); argObj[ key ] = value.replace(/(^")|("$)/g, '');
} }
// Match unnamed argument // Match unnamed argument
const unnamedArgPattern = /(?:\w+=(?:"(?:\\.|[^"\\])*"|\S+)\s*)*(.*)/s; const unnamedArgPattern = /(?:\w+=(?:"(?:\\.|[^"\\])*"|\S+)\s*)*(.*)/s;
match = unnamedArgPattern.exec(args); match = unnamedArgPattern.exec(args);
if (match !== null) { if (match !== null) {
unnamedArg = match[1].trim(); unnamedArg = match[ 1 ].trim();
} }
// Excluded commands format in their own function // Excluded commands format in their own function
@ -113,18 +111,18 @@ class SlashCommandParser {
} }
} }
if (this.commands[command]) { if (this.commands[ command ]) {
return { command: this.commands[command], args: argObj, value: unnamedArg }; return { command: this.commands[ command ], args: argObj, value: unnamedArg };
} }
return false; return false;
} }
getHelpString() { getHelpString () {
const listItems = Object const listItems = Object
.entries(this.helpStrings) .entries(this.helpStrings)
.sort((a, b) => a[0].localeCompare(b[0])) .sort((a, b) => a[ 0 ].localeCompare(b[ 0 ]))
.map(x => x[1]) .map(x => x[ 1 ])
.map(x => `<li>${x}</li>`) .map(x => `<li>${x}</li>`)
.join('\n'); .join('\n');
return `<p>Slash commands:</p><ol>${listItems}</ol> return `<p>Slash commands:</p><ol>${listItems}</ol>
@ -138,48 +136,49 @@ const parser = new SlashCommandParser();
const registerSlashCommand = parser.addCommand.bind(parser); const registerSlashCommand = parser.addCommand.bind(parser);
const getSlashCommandsHelp = parser.getHelpString.bind(parser); const getSlashCommandsHelp = parser.getHelpString.bind(parser);
parser.addCommand('?', helpCommandCallback, ['help'], ' get help on macros, chat formatting and commands', true, true); parser.addCommand('?', helpCommandCallback, [ 'help' ], ' get help on macros, chat formatting and commands', true, true);
parser.addCommand('name', setNameCallback, ['persona'], '<span class="monospace">(name)</span> sets user name and persona avatar (if set)', true, true); parser.addCommand('name', setNameCallback, [ 'persona' ], '<span class="monospace">(name)</span> sets user name and persona avatar (if set)', true, true);
parser.addCommand('sync', syncCallback, [], ' syncs user name in user-attributed messages in the current chat', true, true); parser.addCommand('sync', syncCallback, [], ' syncs user name in user-attributed messages in the current chat', true, true);
parser.addCommand('lock', bindCallback, ['bind'], ' locks/unlocks a persona (name and avatar) to the current chat', true, true); parser.addCommand('lock', bindCallback, [ 'bind' ], ' locks/unlocks a persona (name and avatar) to the current chat', true, true);
parser.addCommand('bg', setBackgroundCallback, ['background'], '<span class="monospace">(filename)</span> sets a background according to filename, partial names allowed', false, true); parser.addCommand('bg', setBackgroundCallback, [ 'background' ], '<span class="monospace">(filename)</span> sets a background according to filename, partial names allowed', false, true);
parser.addCommand('sendas', sendMessageAs, [], ' sends message as a specific character. Uses character avatar if it exists in the characters list. Example that will send "Hello, guys!" from "Chloe": <tt>/sendas name="Chloe" Hello, guys!</tt>', true, true); parser.addCommand('sendas', sendMessageAs, [], ' sends message as a specific character. Uses character avatar if it exists in the characters list. Example that will send "Hello, guys!" from "Chloe": <tt>/sendas name="Chloe" Hello, guys!</tt>', true, true);
parser.addCommand('sys', sendNarratorMessage, ['nar'], '<span class="monospace">(text)</span> sends message as a system narrator', false, true); parser.addCommand('sys', sendNarratorMessage, [ 'nar' ], '<span class="monospace">(text)</span> sends message as a system narrator', false, true);
parser.addCommand('sysname', setNarratorName, [], '<span class="monospace">(name)</span> sets a name for future system narrator messages in this chat (display only). Default: System. Leave empty to reset.', true, true); parser.addCommand('sysname', setNarratorName, [], '<span class="monospace">(name)</span> sets a name for future system narrator messages in this chat (display only). Default: System. Leave empty to reset.', true, true);
parser.addCommand('comment', sendCommentMessage, [], '<span class="monospace">(text)</span> adds a note/comment message not part of the chat', false, true); parser.addCommand('comment', sendCommentMessage, [], '<span class="monospace">(text)</span> adds a note/comment message not part of the chat', false, true);
parser.addCommand('single', setStoryModeCallback, ['story'], ' sets the message style to single document mode without names or avatars visible', true, true); parser.addCommand('single', setStoryModeCallback, [ 'story' ], ' sets the message style to single document mode without names or avatars visible', true, true);
parser.addCommand('bubble', setBubbleModeCallback, ['bubbles'], ' sets the message style to bubble chat mode', true, true); parser.addCommand('bubble', setBubbleModeCallback, [ 'bubbles' ], ' sets the message style to bubble chat mode', true, true);
parser.addCommand('flat', setFlatModeCallback, ['default'], ' sets the message style to flat chat mode', true, true); parser.addCommand('flat', setFlatModeCallback, [ 'default' ], ' sets the message style to flat chat mode', true, true);
parser.addCommand('continue', continueChatCallback, ['cont'], ' continues the last message in the chat', true, true); parser.addCommand('continue', continueChatCallback, [ 'cont' ], ' continues the last message in the chat', true, true);
parser.addCommand('go', goToCharacterCallback, ['char'], '<span class="monospace">(name)</span> opens up a chat with the character by its name', true, true); parser.addCommand('go', goToCharacterCallback, [ 'char' ], '<span class="monospace">(name)</span> opens up a chat with the character by its name', true, true);
parser.addCommand('sysgen', generateSystemMessage, [], '<span class="monospace">(prompt)</span> generates a system message using a specified prompt', true, true); parser.addCommand('sysgen', generateSystemMessage, [], '<span class="monospace">(prompt)</span> generates a system message using a specified prompt', true, true);
parser.addCommand('ask', askCharacter, [], '<span class="monospace">(prompt)</span> asks a specified character card a prompt', true, true); parser.addCommand('ask', askCharacter, [], '<span class="monospace">(prompt)</span> asks a specified character card a prompt', true, true);
parser.addCommand('delname', deleteMessagesByNameCallback, ['cancel'], '<span class="monospace">(name)</span> deletes all messages attributed to a specified name', true, true); parser.addCommand('delname', deleteMessagesByNameCallback, [ 'cancel' ], '<span class="monospace">(name)</span> deletes all messages attributed to a specified name', true, true);
parser.addCommand('send', sendUserMessageCallback, [], '<span class="monospace">(text)</span> adds a user message to the chat log without triggering a generation', true, true); parser.addCommand('send', sendUserMessageCallback, [], '<span class="monospace">(text)</span> adds a user message to the chat log without triggering a generation', true, true);
parser.addCommand('trigger', triggerGenerationCallback, [], ' triggers a message generation. If in group, can trigger a message for the specified group member index or name.', true, true); parser.addCommand('trigger', triggerGenerationCallback, [], ' triggers a message generation. If in group, can trigger a message for the specified group member index or name.', true, true);
parser.addCommand('hide', hideMessageCallback, [], '<span class="monospace">(message index or range)</span> hides a chat message from the prompt', true, true); parser.addCommand('hide', hideMessageCallback, [], '<span class="monospace">(message index or range)</span> hides a chat message from the prompt', true, true);
parser.addCommand('unhide', unhideMessageCallback, [], '<span class="monospace">(message index or range)</span> unhides a message from the prompt', true, true); parser.addCommand('unhide', unhideMessageCallback, [], '<span class="monospace">(message index or range)</span> unhides a message from the prompt', true, true);
parser.addCommand('disable', disableGroupMemberCallback, [], '<span class="monospace">(member index or name)</span> disables a group member from being drafted for replies', true, true); parser.addCommand('disable', disableGroupMemberCallback, [], '<span class="monospace">(member index or name)</span> disables a group member from being drafted for replies', true, true);
parser.addCommand('enable', enableGroupMemberCallback, [], '<span class="monospace">(member index or name)</span> enables a group member to be drafted for replies', true, true); parser.addCommand('enable', enableGroupMemberCallback, [], '<span class="monospace">(member index or name)</span> enables a group member to be drafted for replies', true, true);
parser.addCommand('memberadd', addGroupMemberCallback, ['addmember'], '<span class="monospace">(character name)</span> adds a new group member to the group chat', true, true); parser.addCommand('memberadd', addGroupMemberCallback, [ 'addmember' ], '<span class="monospace">(character name)</span> adds a new group member to the group chat', true, true);
parser.addCommand('memberremove', removeGroupMemberCallback, ['removemember'], '<span class="monospace">(member index or name)</span> removes a group member from the group chat', true, true); parser.addCommand('memberremove', removeGroupMemberCallback, [ 'removemember' ], '<span class="monospace">(member index or name)</span> removes a group member from the group chat', true, true);
parser.addCommand('memberup', moveGroupMemberUpCallback, ['upmember'], '<span class="monospace">(member index or name)</span> moves a group member up in the group chat list', true, true); parser.addCommand('memberup', moveGroupMemberUpCallback, [ 'upmember' ], '<span class="monospace">(member index or name)</span> moves a group member up in the group chat list', true, true);
parser.addCommand('memberdown', moveGroupMemberDownCallback, ['downmember'], '<span class="monospace">(member index or name)</span> moves a group member down in the group chat list', true, true); parser.addCommand('memberdown', moveGroupMemberDownCallback, [ 'downmember' ], '<span class="monospace">(member index or name)</span> moves a group member down in the group chat list', true, true);
parser.addCommand('peek', peekCallback, [], '<span class="monospace">(message index or range)</span> shows a group member character card without switching chats', true, true); parser.addCommand('peek', peekCallback, [], '<span class="monospace">(message index or range)</span> shows a group member character card without switching chats', true, true);
parser.addCommand('delswipe', deleteSwipeCallback, ['swipedel'], '<span class="monospace">(optional 1-based id)</span> deletes a swipe from the last chat message. If swipe id not provided - deletes the current swipe.', true, true); parser.addCommand('delswipe', deleteSwipeCallback, [ 'swipedel' ], '<span class="monospace">(optional 1-based id)</span> deletes a swipe from the last chat message. If swipe id not provided - deletes the current swipe.', true, true);
parser.addCommand('echo', echoCallback, [], '<span class="monospace">(text)</span> echoes the text to toast message. Useful for pipes debugging.', true, true); parser.addCommand('echo', echoCallback, [], '<span class="monospace">(title=string severity=info/warning/error/success [text])</span> echoes the text to toast message. Useful for pipes debugging.', true, true);
// '<span class="monospace">(text)</span> echoes the text to toast message. Useful for pipes debugging.', true, true);
parser.addCommand('gen', generateCallback, [], '<span class="monospace">(lock=on/off [prompt])</span> generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating.', true, true); parser.addCommand('gen', generateCallback, [], '<span class="monospace">(lock=on/off [prompt])</span> generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating.', true, true);
parser.addCommand('genraw', generateRawCallback, [], '<span class="monospace">(lock=on/off [prompt])</span> generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating. Does not include chat history or character card. Use instruct=off to skip instruct formatting, e.g. <tt>/genraw instruct=off Why is the sky blue?</tt>. Use stop=... with a JSON-serialized array to add one-time custom stop strings, e.g. <tt>/genraw stop=["\\n"] Say hi</tt>', true, true); parser.addCommand('genraw', generateRawCallback, [], '<span class="monospace">(lock=on/off [prompt])</span> generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating. Does not include chat history or character card. Use instruct=off to skip instruct formatting, e.g. <tt>/genraw instruct=off Why is the sky blue?</tt>. Use stop=... with a JSON-serialized array to add one-time custom stop strings, e.g. <tt>/genraw stop=["\\n"] Say hi</tt>', true, true);
parser.addCommand('addswipe', addSwipeCallback, ['swipeadd'], '<span class="monospace">(text)</span> adds a swipe to the last chat message.', true, true); parser.addCommand('addswipe', addSwipeCallback, [ 'swipeadd' ], '<span class="monospace">(text)</span> adds a swipe to the last chat message.', true, true);
parser.addCommand('abort', abortCallback, [], ' aborts the slash command batch execution', true, true); parser.addCommand('abort', abortCallback, [], ' aborts the slash command batch execution', true, true);
parser.addCommand('fuzzy', fuzzyCallback, [], 'list=["a","b","c"] (search value) performs a fuzzy match of the provided search using the provided list of value and passes the closest match to the next command through the pipe.', true, true); parser.addCommand('fuzzy', fuzzyCallback, [], 'list=["a","b","c"] (search value) performs a fuzzy match of the provided search using the provided list of value and passes the closest match to the next command through the pipe.', true, true);
parser.addCommand('pass', (_, arg) => arg, ['return'], '<span class="monospace">(text)</span> passes the text to the next command through the pipe.', true, true); parser.addCommand('pass', (_, arg) => arg, [ 'return' ], '<span class="monospace">(text)</span> passes the text to the next command through the pipe.', true, true);
parser.addCommand('delay', delayCallback, ['wait', 'sleep'], '<span class="monospace">(milliseconds)</span> delays the next command in the pipe by the specified number of milliseconds.', true, true); parser.addCommand('delay', delayCallback, [ 'wait', 'sleep' ], '<span class="monospace">(milliseconds)</span> delays the next command in the pipe by the specified number of milliseconds.', true, true);
parser.addCommand('input', inputCallback, ['prompt'], '<span class="monospace">(prompt)</span> shows a popup with the provided prompt and passes the user input to the next command through the pipe.', true, true); parser.addCommand('input', inputCallback, [ 'prompt' ], '<span class="monospace">(input="string" large=on/off wide=on/off okButton="string" rows=number text)</span> Shows a popup with the provided text and an input field. The input argument is the default value of the input field, and the text argument is the text to display.', true, true);
parser.addCommand('run', runCallback, ['call', 'exec'], '<span class="monospace">(QR label)</span> runs a Quick Reply with the specified name from the current preset.', true, true); parser.addCommand('run', runCallback, [ 'call', 'exec' ], '<span class="monospace">(QR label)</span> runs a Quick Reply with the specified name from the current preset.', true, true);
parser.addCommand('messages', getMessagesCallback, ['message'], '<span class="monospace">(names=off/on [message index or range])</span> returns the specified message or range of messages as a string.', true, true); parser.addCommand('messages', getMessagesCallback, [ 'message' ], '<span class="monospace">(names=off/on [message index or range])</span> returns the specified message or range of messages as a string.', true, true);
parser.addCommand('setinput', setInputCallback, [], '<span class="monospace">(text)</span> sets the user input to the specified text and passes it to the next command through the pipe.', true, true); parser.addCommand('setinput', setInputCallback, [], '<span class="monospace">(text)</span> sets the user input to the specified text and passes it to the next command through the pipe.', true, true);
parser.addCommand('popup', popupCallback, [], '<span class="monospace">(text)</span> shows a blocking popup with the specified text.', true, true); parser.addCommand('popup', popupCallback, [], '<span class="monospace">(large=on/off wide=on/off okButton="string" text)</span> shows a blocking popup with the specified text and buttons. Returns the input value into the pipe or empty string if canceled.', true, true);
parser.addCommand('buttons', buttonsCallback, [], '<span class="monospace">labels=["a","b"] (text)</span> shows a blocking popup with the specified text and buttons. Returns the clicked button label into the pipe or empty string if canceled.', true, true); parser.addCommand('buttons', buttonsCallback, [], '<span class="monospace">labels=["a","b"] (text)</span> shows a blocking popup with the specified text and buttons. Returns the clicked button label into the pipe or empty string if canceled.', true, true);
parser.addCommand('trimtokens', trimTokensCallback, [], '<span class="monospace">limit=number (direction=start/end [text])</span> trims the start or end of text to the specified number of tokens.', true, true); parser.addCommand('trimtokens', trimTokensCallback, [], '<span class="monospace">limit=number (direction=start/end [text])</span> trims the start or end of text to the specified number of tokens.', true, true);
parser.addCommand('trimstart', trimStartCallback, [], '<span class="monospace">(text)</span> trims the text to the start of the first full sentence.', true, true); parser.addCommand('trimstart', trimStartCallback, [], '<span class="monospace">(text)</span> trims the text to the start of the first full sentence.', true, true);
@ -194,7 +193,7 @@ const NARRATOR_NAME_DEFAULT = 'System';
export const COMMENT_NAME_DEFAULT = 'Note'; export const COMMENT_NAME_DEFAULT = 'Note';
const SCRIPT_PROMPT_KEY = 'script_inject_'; const SCRIPT_PROMPT_KEY = 'script_inject_';
function injectCallback(args, value) { function injectCallback (args, value) {
const positions = { const positions = {
'before': extension_prompt_types.BEFORE_PROMPT, 'before': extension_prompt_types.BEFORE_PROMPT,
'after': extension_prompt_types.IN_PROMPT, 'after': extension_prompt_types.IN_PROMPT,
@ -212,7 +211,7 @@ function injectCallback(args, value) {
const defaultPosition = 'after'; const defaultPosition = 'after';
const defaultDepth = 4; const defaultDepth = 4;
const positionValue = args?.position ?? defaultPosition; const positionValue = args?.position ?? defaultPosition;
const position = positions[positionValue] ?? positions[defaultPosition]; const position = positions[ positionValue ] ?? positions[ defaultPosition ];
const depthValue = Number(args?.depth) ?? defaultDepth; const depthValue = Number(args?.depth) ?? defaultDepth;
const depth = isNaN(depthValue) ? defaultDepth : depthValue; const depth = isNaN(depthValue) ? defaultDepth : depthValue;
value = value || ''; value = value || '';
@ -223,7 +222,7 @@ function injectCallback(args, value) {
chat_metadata.script_injects = {}; chat_metadata.script_injects = {};
} }
chat_metadata.script_injects[id] = { chat_metadata.script_injects[ id ] = {
value, value,
position, position,
depth, depth,
@ -234,16 +233,16 @@ function injectCallback(args, value) {
return ''; return '';
} }
function listInjectsCallback() { function listInjectsCallback () {
if (!chat_metadata.script_injects) { if (!chat_metadata.script_injects) {
toastr.info('No script injections for the current chat'); toastr.info('No script injections for the current chat');
return ''; return '';
} }
const injects = Object.entries(chat_metadata.script_injects) const injects = Object.entries(chat_metadata.script_injects)
.map(([id, inject]) => { .map(([ id, inject ]) => {
const position = Object.entries(extension_prompt_types); const position = Object.entries(extension_prompt_types);
const positionName = position.find(([_, value]) => value === inject.position)?.[0] ?? 'unknown'; const positionName = position.find(([ _, value ]) => value === inject.position)?.[ 0 ] ?? 'unknown';
return `* **${id}**: <code>${inject.value}</code> (${positionName}, depth: ${inject.depth})`; return `* **${id}**: <code>${inject.value}</code> (${positionName}, depth: ${inject.depth})`;
}) })
.join('\n'); .join('\n');
@ -255,12 +254,12 @@ function listInjectsCallback() {
sendSystemMessage(system_message_types.GENERIC, htmlMessage); sendSystemMessage(system_message_types.GENERIC, htmlMessage);
} }
function flushInjectsCallback() { function flushInjectsCallback () {
if (!chat_metadata.script_injects) { if (!chat_metadata.script_injects) {
return ''; return '';
} }
for (const [id, inject] of Object.entries(chat_metadata.script_injects)) { for (const [ id, inject ] of Object.entries(chat_metadata.script_injects)) {
const prefixedId = `${SCRIPT_PROMPT_KEY}${id}`; const prefixedId = `${SCRIPT_PROMPT_KEY}${id}`;
setExtensionPrompt(prefixedId, '', inject.position, inject.depth); setExtensionPrompt(prefixedId, '', inject.position, inject.depth);
} }
@ -270,7 +269,7 @@ function flushInjectsCallback() {
return ''; return '';
} }
export function processChatSlashCommands() { export function processChatSlashCommands () {
const context = getContext(); const context = getContext();
if (!(context.chatMetadata.script_injects)) { if (!(context.chatMetadata.script_injects)) {
@ -283,22 +282,22 @@ export function processChatSlashCommands() {
} }
console.log('Removing script injection', id); console.log('Removing script injection', id);
delete context.extensionPrompts[id]; delete context.extensionPrompts[ id ];
} }
for (const [id, inject] of Object.entries(context.chatMetadata.script_injects)) { for (const [ id, inject ] of Object.entries(context.chatMetadata.script_injects)) {
const prefixedId = `${SCRIPT_PROMPT_KEY}${id}`; const prefixedId = `${SCRIPT_PROMPT_KEY}${id}`;
console.log('Adding script injection', id); console.log('Adding script injection', id);
setExtensionPrompt(prefixedId, inject.value, inject.position, inject.depth); setExtensionPrompt(prefixedId, inject.value, inject.position, inject.depth);
} }
} }
function setInputCallback(_, value) { function setInputCallback (_, value) {
$('#send_textarea').val(value || '').trigger('input'); $('#send_textarea').val(value || '').trigger('input');
return value; return value;
} }
function trimStartCallback(_, value) { function trimStartCallback (_, value) {
if (!value) { if (!value) {
return ''; return '';
} }
@ -306,7 +305,7 @@ function trimStartCallback(_, value) {
return trimToStartSentence(value); return trimToStartSentence(value);
} }
function trimEndCallback(_, value) { function trimEndCallback (_, value) {
if (!value) { if (!value) {
return ''; return '';
} }
@ -314,7 +313,7 @@ function trimEndCallback(_, value) {
return trimToEndSentence(value); return trimToEndSentence(value);
} }
function trimTokensCallback(arg, value) { function trimTokensCallback (arg, value) {
if (!value) { if (!value) {
console.warn('WARN: No argument provided for /trimtokens command'); console.warn('WARN: No argument provided for /trimtokens command');
return ''; return '';
@ -362,7 +361,7 @@ function trimTokensCallback(arg, value) {
} }
} }
async function buttonsCallback(args, text) { async function buttonsCallback (args, text) {
try { try {
const buttons = JSON.parse(resolveVariable(args?.labels)); const buttons = JSON.parse(resolveVariable(args?.labels));
@ -400,15 +399,20 @@ async function buttonsCallback(args, text) {
} }
} }
async function popupCallback(_, value) { async function popupCallback (args, value) {
const safeValue = DOMPurify.sanitize(value || ''); const safeValue = DOMPurify.sanitize(value || '');
const popupOptions ={
large: isTrueBoolean(args?.large),
wide: isTrueBoolean(args?.wide),
okButton: args?.okButton !== undefined && typeof args?.okButton === 'string' ? args.okButton : 'Ok',
};
await delay(1); await delay(1);
await callPopup(safeValue, 'text', ''); await callPopup(safeValue, 'text', '', popupOptions);
await delay(1); await delay(1);
return value; return value;
} }
function getMessagesCallback(args, value) { function getMessagesCallback (args, value) {
const includeNames = !isFalseBoolean(args?.names); const includeNames = !isFalseBoolean(args?.names);
const range = stringToRange(value, 0, chat.length - 1); const range = stringToRange(value, 0, chat.length - 1);
@ -420,7 +424,7 @@ function getMessagesCallback(args, value) {
const messages = []; const messages = [];
for (let messageId = range.start; messageId <= range.end; messageId++) { for (let messageId = range.start; messageId <= range.end; messageId++) {
const message = chat[messageId]; const message = chat[ messageId ];
if (!message) { if (!message) {
console.warn(`WARN: No message found with ID ${messageId}`); console.warn(`WARN: No message found with ID ${messageId}`);
continue; continue;
@ -440,32 +444,32 @@ function getMessagesCallback(args, value) {
return messages.join('\n\n'); return messages.join('\n\n');
} }
async function runCallback(_, name) { async function runCallback (_, name) {
if (!name) { if (!name) {
toastr.warning('No name provided for /run command'); toastr.warning('No name provided for /run command');
return ''; return '';
} }
if (typeof window['executeQuickReplyByName'] !== 'function') { if (typeof window[ 'executeQuickReplyByName' ] !== 'function') {
toastr.warning('Quick Reply extension is not loaded'); toastr.warning('Quick Reply extension is not loaded');
return ''; return '';
} }
try { try {
name = name.trim(); name = name.trim();
return await window['executeQuickReplyByName'](name); return await window[ 'executeQuickReplyByName' ](name);
} catch (error) { } catch (error) {
toastr.error(`Error running Quick Reply "${name}": ${error.message}`, 'Error'); toastr.error(`Error running Quick Reply "${name}": ${error.message}`, 'Error');
return ''; return '';
} }
} }
function abortCallback() { function abortCallback () {
$('#send_textarea').val('').trigger('input'); $('#send_textarea').val('').trigger('input');
throw new Error('/abort command executed'); throw new Error('/abort command executed');
} }
async function delayCallback(_, amount) { async function delayCallback (_, amount) {
if (!amount) { if (!amount) {
console.warn('WARN: No amount provided for /delay command'); console.warn('WARN: No amount provided for /delay command');
return; return;
@ -479,16 +483,23 @@ async function delayCallback(_, amount) {
await delay(amount); await delay(amount);
} }
async function inputCallback(_, prompt) { async function inputCallback (args, prompt) {
const safeValue = DOMPurify.sanitize(prompt || '');
const input = args?.input !== undefined && typeof args?.input === 'string' ? args.input : '';
const popupOptions = {
large: isTrueBoolean(args?.large),
wide: isTrueBoolean(args?.wide),
okButton: args?.okButton !== undefined && typeof args?.okButton === 'string' ? args.okButton : 'Ok',
rows: args?.rows !== undefined && typeof args?.rows === 'string' ? isNaN(Number(args.rows)) ? 4 : Number(args.rows) : 4,
};
// Do not remove this delay, otherwise the prompt will not show up // Do not remove this delay, otherwise the prompt will not show up
await delay(1); await delay(1);
const safeValue = DOMPurify.sanitize(prompt || ''); const result = await callPopup(safeValue, 'input', input, popupOptions);
const result = await callPopup(safeValue, 'input', '', { okButton: 'Ok' });
await delay(1); await delay(1);
return result || ''; return result || '';
} }
function fuzzyCallback(args, value) { function fuzzyCallback (args, value) {
if (!value) { if (!value) {
console.warn('WARN: No argument provided for /fuzzy command'); console.warn('WARN: No argument provided for /fuzzy command');
return ''; return '';
@ -513,7 +524,7 @@ function fuzzyCallback(args, value) {
threshold: 0.7, threshold: 0.7,
}); });
const result = fuse.search(value); const result = fuse.search(value);
return result[0]?.item; return result[ 0 ]?.item;
} catch { } catch {
console.warn('WARN: Invalid list argument provided for /fuzzy command'); console.warn('WARN: Invalid list argument provided for /fuzzy command');
return ''; return '';
@ -525,9 +536,7 @@ function setEphemeralStopStrings(value) {
try { try {
const stopStrings = JSON.parse(value); const stopStrings = JSON.parse(value);
if (Array.isArray(stopStrings)) { if (Array.isArray(stopStrings)) {
for (const stopString of stopStrings) { stopStrings.forEach(stopString => addEphemeralStoppingString(stopString));
addEphemeralStoppingString(stopString);
}
} }
} catch { } catch {
// Do nothing // Do nothing
@ -535,7 +544,7 @@ function setEphemeralStopStrings(value) {
} }
} }
async function generateRawCallback(args, value) { async function generateRawCallback (args, value) {
if (!value) { if (!value) {
console.warn('WARN: No argument provided for /genraw command'); console.warn('WARN: No argument provided for /genraw command');
return; return;
@ -561,7 +570,7 @@ async function generateRawCallback(args, value) {
} }
} }
async function generateCallback(args, value) { async function generateCallback (args, value) {
if (!value) { if (!value) {
console.warn('WARN: No argument provided for /gen command'); console.warn('WARN: No argument provided for /gen command');
return; return;
@ -587,18 +596,33 @@ async function generateCallback(args, value) {
} }
} }
async function echoCallback(_, arg) { async function echoCallback (args, value) {
if (!String(arg)) { const safeValue = DOMPurify.sanitize(value || '');
if (safeValue=== '') {
console.warn('WARN: No argument provided for /echo command'); console.warn('WARN: No argument provided for /echo command');
return; return;
} }
const title = args?.title !== undefined && typeof args?.title === 'string' ? args.title : undefined;
toastr.info(String(arg)); const severity = args?.severity!== undefined && typeof args?.severity === 'string' ? args.severity : 'info';
return arg; switch (severity) {
case 'error':
toastr.error(safeValue, title);
break;
case 'warning':
toastr.warning(safeValue, title);
break;
case 'success':
toastr.success(safeValue, title);
break;
case 'info':
default:
toastr.info(safeValue, title);
break;
}
} }
async function addSwipeCallback(_, arg) { async function addSwipeCallback (_, arg) {
const lastMessage = chat[chat.length - 1]; const lastMessage = chat[ chat.length - 1 ];
if (!lastMessage) { if (!lastMessage) {
toastr.warning('No messages to add swipes to.'); toastr.warning('No messages to add swipes to.');
@ -626,8 +650,8 @@ async function addSwipeCallback(_, arg) {
} }
if (!Array.isArray(lastMessage.swipes)) { if (!Array.isArray(lastMessage.swipes)) {
lastMessage.swipes = [lastMessage.mes]; lastMessage.swipes = [ lastMessage.mes ];
lastMessage.swipe_info = [{}]; lastMessage.swipe_info = [ {} ];
lastMessage.swipe_id = 0; lastMessage.swipe_id = 0;
} }
@ -648,8 +672,8 @@ async function addSwipeCallback(_, arg) {
await reloadCurrentChat(); await reloadCurrentChat();
} }
async function deleteSwipeCallback(_, arg) { async function deleteSwipeCallback (_, arg) {
const lastMessage = chat[chat.length - 1]; const lastMessage = chat[ chat.length - 1 ];
if (!lastMessage || !Array.isArray(lastMessage.swipes) || !lastMessage.swipes.length) { if (!lastMessage || !Array.isArray(lastMessage.swipes) || !lastMessage.swipes.length) {
toastr.warning('No messages to delete swipes from.'); toastr.warning('No messages to delete swipes from.');
@ -676,13 +700,13 @@ async function deleteSwipeCallback(_, arg) {
const newSwipeId = Math.min(swipeId, lastMessage.swipes.length - 1); const newSwipeId = Math.min(swipeId, lastMessage.swipes.length - 1);
lastMessage.swipe_id = newSwipeId; lastMessage.swipe_id = newSwipeId;
lastMessage.mes = lastMessage.swipes[newSwipeId]; lastMessage.mes = lastMessage.swipes[ newSwipeId ];
await saveChatConditional(); await saveChatConditional();
await reloadCurrentChat(); await reloadCurrentChat();
} }
async function askCharacter(_, text) { async function askCharacter (_, text) {
// Prevent generate recursion // Prevent generate recursion
$('#send_textarea').val('').trigger('input'); $('#send_textarea').val('').trigger('input');
@ -710,7 +734,7 @@ async function askCharacter(_, text) {
// Find the character // Find the character
const chId = characters.findIndex((e) => e.name === name); const chId = characters.findIndex((e) => e.name === name);
if (!characters[chId] || chId === -1) { if (!characters[ chId ] || chId === -1) {
toastr.error('Character not found.'); toastr.error('Character not found.');
return; return;
} }
@ -719,7 +743,7 @@ async function askCharacter(_, text) {
setCharacterId(chId); setCharacterId(chId);
// TODO: Maybe look up by filename instead of name // TODO: Maybe look up by filename instead of name
const character = characters[chId]; const character = characters[ chId ];
let force_avatar, original_avatar; let force_avatar, original_avatar;
if (character && character.avatar !== 'none') { if (character && character.avatar !== 'none') {
@ -737,11 +761,11 @@ async function askCharacter(_, text) {
const restoreCharacter = () => { const restoreCharacter = () => {
setCharacterId(prevChId); setCharacterId(prevChId);
setCharacterName(characters[prevChId].name); setCharacterName(characters[ prevChId ].name);
// Only force the new avatar if the character name is the same // Only force the new avatar if the character name is the same
// This skips if an error was fired // This skips if an error was fired
const lastMessage = chat[chat.length - 1]; const lastMessage = chat[ chat.length - 1 ];
if (lastMessage && lastMessage?.name === character.name) { if (lastMessage && lastMessage?.name === character.name) {
lastMessage.force_avatar = force_avatar; lastMessage.force_avatar = force_avatar;
lastMessage.original_avatar = original_avatar; lastMessage.original_avatar = original_avatar;
@ -764,7 +788,7 @@ async function askCharacter(_, text) {
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, restoreCharacter); eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, restoreCharacter);
} }
async function hideMessageCallback(_, arg) { async function hideMessageCallback (_, arg) {
if (!arg) { if (!arg) {
console.warn('WARN: No argument provided for /hide command'); console.warn('WARN: No argument provided for /hide command');
return; return;
@ -789,7 +813,7 @@ async function hideMessageCallback(_, arg) {
} }
} }
async function unhideMessageCallback(_, arg) { async function unhideMessageCallback (_, arg) {
if (!arg) { if (!arg) {
console.warn('WARN: No argument provided for /unhide command'); console.warn('WARN: No argument provided for /unhide command');
return ''; return '';
@ -816,7 +840,7 @@ async function unhideMessageCallback(_, arg) {
return ''; return '';
} }
async function disableGroupMemberCallback(_, arg) { async function disableGroupMemberCallback (_, arg) {
if (!selected_group) { if (!selected_group) {
toastr.warning('Cannot run /disable command outside of a group chat.'); toastr.warning('Cannot run /disable command outside of a group chat.');
return ''; return '';
@ -833,7 +857,7 @@ async function disableGroupMemberCallback(_, arg) {
return ''; return '';
} }
async function enableGroupMemberCallback(_, arg) { async function enableGroupMemberCallback (_, arg) {
if (!selected_group) { if (!selected_group) {
toastr.warning('Cannot run /enable command outside of a group chat.'); toastr.warning('Cannot run /enable command outside of a group chat.');
return ''; return '';
@ -850,7 +874,7 @@ async function enableGroupMemberCallback(_, arg) {
return ''; return '';
} }
async function moveGroupMemberUpCallback(_, arg) { async function moveGroupMemberUpCallback (_, arg) {
if (!selected_group) { if (!selected_group) {
toastr.warning('Cannot run /memberup command outside of a group chat.'); toastr.warning('Cannot run /memberup command outside of a group chat.');
return ''; return '';
@ -867,7 +891,7 @@ async function moveGroupMemberUpCallback(_, arg) {
return ''; return '';
} }
async function moveGroupMemberDownCallback(_, arg) { async function moveGroupMemberDownCallback (_, arg) {
if (!selected_group) { if (!selected_group) {
toastr.warning('Cannot run /memberdown command outside of a group chat.'); toastr.warning('Cannot run /memberdown command outside of a group chat.');
return ''; return '';
@ -884,7 +908,7 @@ async function moveGroupMemberDownCallback(_, arg) {
return ''; return '';
} }
async function peekCallback(_, arg) { async function peekCallback (_, arg) {
if (!selected_group) { if (!selected_group) {
toastr.warning('Cannot run /peek command outside of a group chat.'); toastr.warning('Cannot run /peek command outside of a group chat.');
return ''; return '';
@ -906,7 +930,7 @@ async function peekCallback(_, arg) {
return ''; return '';
} }
async function removeGroupMemberCallback(_, arg) { async function removeGroupMemberCallback (_, arg) {
if (!selected_group) { if (!selected_group) {
toastr.warning('Cannot run /memberremove command outside of a group chat.'); toastr.warning('Cannot run /memberremove command outside of a group chat.');
return ''; return '';
@ -928,7 +952,7 @@ async function removeGroupMemberCallback(_, arg) {
return ''; return '';
} }
async function addGroupMemberCallback(_, arg) { async function addGroupMemberCallback (_, arg) {
if (!selected_group) { if (!selected_group) {
toastr.warning('Cannot run /memberadd command outside of a group chat.'); toastr.warning('Cannot run /memberadd command outside of a group chat.');
return ''; return '';
@ -947,7 +971,7 @@ async function addGroupMemberCallback(_, arg) {
return ''; return '';
} }
const character = characters[chid]; const character = characters[ chid ];
const group = groups.find(x => x.id === selected_group); const group = groups.find(x => x.id === selected_group);
if (!group || !Array.isArray(group.members)) { if (!group || !Array.isArray(group.members)) {
@ -970,7 +994,7 @@ async function addGroupMemberCallback(_, arg) {
return character.name; return character.name;
} }
async function triggerGenerationCallback(_, arg) { async function triggerGenerationCallback (_, arg) {
setTimeout(async () => { setTimeout(async () => {
try { try {
await waitUntilCondition(() => !is_send_press && !is_group_generating, 10000, 100); await waitUntilCondition(() => !is_send_press && !is_group_generating, 10000, 100);
@ -999,7 +1023,7 @@ async function triggerGenerationCallback(_, arg) {
return ''; return '';
} }
async function sendUserMessageCallback(args, text) { async function sendUserMessageCallback (args, text) {
if (!text) { if (!text) {
console.warn('WARN: No text provided for /send command'); console.warn('WARN: No text provided for /send command');
return; return;
@ -1012,7 +1036,7 @@ async function sendUserMessageCallback(args, text) {
return ''; return '';
} }
async function deleteMessagesByNameCallback(_, name) { async function deleteMessagesByNameCallback (_, name) {
if (!name) { if (!name) {
console.warn('WARN: No name provided for /delname command'); console.warn('WARN: No name provided for /delname command');
return; return;
@ -1047,7 +1071,7 @@ async function deleteMessagesByNameCallback(_, name) {
return ''; return '';
} }
function findCharacterIndex(name) { function findCharacterIndex (name) {
const matchTypes = [ const matchTypes = [
(a, b) => a === b, (a, b) => a === b,
(a, b) => a.startsWith(b), (a, b) => a.startsWith(b),
@ -1064,7 +1088,7 @@ function findCharacterIndex(name) {
return -1; return -1;
} }
async function goToCharacterCallback(_, name) { async function goToCharacterCallback (_, name) {
if (!name) { if (!name) {
console.warn('WARN: No character name provided for /go command'); console.warn('WARN: No character name provided for /go command');
return; return;
@ -1075,21 +1099,21 @@ async function goToCharacterCallback(_, name) {
if (characterIndex !== -1) { if (characterIndex !== -1) {
await openChat(new String(characterIndex)); await openChat(new String(characterIndex));
return characters[characterIndex]?.name; return characters[ characterIndex ]?.name;
} else { } else {
console.warn(`No matches found for name "${name}"`); console.warn(`No matches found for name "${name}"`);
return ''; return '';
} }
} }
async function openChat(id) { async function openChat (id) {
resetSelectedGroup(); resetSelectedGroup();
setCharacterId(id); setCharacterId(id);
await delay(1); await delay(1);
await reloadCurrentChat(); await reloadCurrentChat();
} }
function continueChatCallback() { function continueChatCallback () {
setTimeout(async () => { setTimeout(async () => {
try { try {
await waitUntilCondition(() => !is_send_press && !is_group_generating, 10000, 100); await waitUntilCondition(() => !is_send_press && !is_group_generating, 10000, 100);
@ -1106,7 +1130,7 @@ function continueChatCallback() {
return ''; return '';
} }
export async function generateSystemMessage(_, prompt) { export async function generateSystemMessage (_, prompt) {
$('#send_textarea').val('').trigger('input'); $('#send_textarea').val('').trigger('input');
if (!prompt) { if (!prompt) {
@ -1123,27 +1147,27 @@ export async function generateSystemMessage(_, prompt) {
sendNarratorMessage(_, message); sendNarratorMessage(_, message);
} }
function syncCallback() { function syncCallback () {
$('#sync_name_button').trigger('click'); $('#sync_name_button').trigger('click');
} }
function bindCallback() { function bindCallback () {
$('#lock_user_name').trigger('click'); $('#lock_user_name').trigger('click');
} }
function setStoryModeCallback() { function setStoryModeCallback () {
$('#chat_display').val(chat_styles.DOCUMENT).trigger('change'); $('#chat_display').val(chat_styles.DOCUMENT).trigger('change');
} }
function setBubbleModeCallback() { function setBubbleModeCallback () {
$('#chat_display').val(chat_styles.BUBBLES).trigger('change'); $('#chat_display').val(chat_styles.BUBBLES).trigger('change');
} }
function setFlatModeCallback() { function setFlatModeCallback () {
$('#chat_display').val(chat_styles.DEFAULT).trigger('change'); $('#chat_display').val(chat_styles.DEFAULT).trigger('change');
} }
function setNameCallback(_, name) { function setNameCallback (_, name) {
if (!name) { if (!name) {
toastr.warning('you must specify a name to change to'); toastr.warning('you must specify a name to change to');
return; return;
@ -1163,14 +1187,14 @@ function setNameCallback(_, name) {
setUserName(name); //this prevented quickReply usage setUserName(name); //this prevented quickReply usage
} }
async function setNarratorName(_, text) { async function setNarratorName (_, text) {
const name = text || NARRATOR_NAME_DEFAULT; const name = text || NARRATOR_NAME_DEFAULT;
chat_metadata[NARRATOR_NAME_KEY] = name; chat_metadata[ NARRATOR_NAME_KEY ] = name;
toastr.info(`System narrator name set to ${name}`); toastr.info(`System narrator name set to ${name}`);
await saveChatConditional(); await saveChatConditional();
} }
export async function sendMessageAs(args, text) { export async function sendMessageAs (args, text) {
if (!text) { if (!text) {
return; return;
} }
@ -1247,12 +1271,12 @@ export async function sendMessageAs(args, text) {
} }
} }
export async function sendNarratorMessage(args, text) { export async function sendNarratorMessage (args, text) {
if (!text) { if (!text) {
return; return;
} }
const name = chat_metadata[NARRATOR_NAME_KEY] || NARRATOR_NAME_DEFAULT; const name = chat_metadata[ NARRATOR_NAME_KEY ] || NARRATOR_NAME_DEFAULT;
// Messages that do nothing but set bias will be hidden from the context // Messages that do nothing but set bias will be hidden from the context
const bias = extractMessageBias(text); const bias = extractMessageBias(text);
const isSystem = replaceBiasMarkup(text).trim().length === 0; const isSystem = replaceBiasMarkup(text).trim().length === 0;
@ -1288,7 +1312,7 @@ export async function sendNarratorMessage(args, text) {
} }
} }
export async function promptQuietForLoudResponse(who, text) { export async function promptQuietForLoudResponse (who, text) {
let character_id = getContext().characterId; let character_id = getContext().characterId;
if (who === 'sys') { if (who === 'sys') {
@ -1296,7 +1320,7 @@ export async function promptQuietForLoudResponse(who, text) {
} else if (who === 'user') { } else if (who === 'user') {
text = name1 + ': ' + text; text = name1 + ': ' + text;
} else if (who === 'char') { } else if (who === 'char') {
text = characters[character_id].name + ': ' + text; text = characters[ character_id ].name + ': ' + text;
} else if (who === 'raw') { } else if (who === 'raw') {
// We don't need to modify the text // We don't need to modify the text
} }
@ -1307,7 +1331,7 @@ export async function promptQuietForLoudResponse(who, text) {
text = await getRegexedString(reply, regex_placement.SLASH_COMMAND); text = await getRegexedString(reply, regex_placement.SLASH_COMMAND);
const message = { const message = {
name: characters[character_id].name, name: characters[ character_id ].name,
is_user: false, is_user: false,
is_name: true, is_name: true,
is_system: false, is_system: false,
@ -1327,7 +1351,7 @@ export async function promptQuietForLoudResponse(who, text) {
} }
async function sendCommentMessage(args, text) { async function sendCommentMessage (args, text) {
if (!text) { if (!text) {
return; return;
} }
@ -1367,7 +1391,7 @@ async function sendCommentMessage(args, text) {
* @param {any} _ Unused * @param {any} _ Unused
* @param {string} type Type of help to display * @param {string} type Type of help to display
*/ */
function helpCommandCallback(_, type) { function helpCommandCallback (_, type) {
switch (type?.trim()?.toLowerCase()) { switch (type?.trim()?.toLowerCase()) {
case 'slash': case 'slash':
case 'commands': case 'commands':
@ -1405,7 +1429,7 @@ $(document).on('click', '[data-displayHelp]', function (e) {
helpCommandCallback(null, page); helpCommandCallback(null, page);
}); });
function setBackgroundCallback(_, bg) { function setBackgroundCallback (_, bg) {
if (!bg) { if (!bg) {
return; return;
} }
@ -1414,7 +1438,7 @@ function setBackgroundCallback(_, bg) {
const bgElements = Array.from(document.querySelectorAll('.bg_example')).map((x) => ({ element: x, bgfile: x.getAttribute('bgfile') })); const bgElements = Array.from(document.querySelectorAll('.bg_example')).map((x) => ({ element: x, bgfile: x.getAttribute('bgfile') }));
const fuse = new Fuse(bgElements, { keys: ['bgfile'] }); const fuse = new Fuse(bgElements, { keys: [ 'bgfile' ] });
const result = fuse.search(bg); const result = fuse.search(bg);
if (!result.length) { if (!result.length) {
@ -1422,7 +1446,7 @@ function setBackgroundCallback(_, bg) {
return; return;
} }
const bgElement = result[0].item.element; const bgElement = result[ 0 ].item.element;
if (bgElement instanceof HTMLElement) { if (bgElement instanceof HTMLElement) {
bgElement.click(); bgElement.click();
@ -1435,7 +1459,7 @@ function setBackgroundCallback(_, bg) {
* @param {boolean} unescape Whether to unescape the batch separator * @param {boolean} unescape Whether to unescape the batch separator
* @returns {Promise<{interrupt: boolean, newText: string, pipe: string} | boolean>} * @returns {Promise<{interrupt: boolean, newText: string, pipe: string} | boolean>}
*/ */
async function executeSlashCommands(text, unescape = false) { async function executeSlashCommands (text, unescape = false) {
if (!text) { if (!text) {
return false; return false;
} }
@ -1452,8 +1476,8 @@ async function executeSlashCommands(text, unescape = false) {
const placeholder = '\u200B'; // Use a zero-width space as a placeholder const placeholder = '\u200B'; // Use a zero-width space as a placeholder
const chars = text.split(''); const chars = text.split('');
for (let i = 1; i < chars.length; i++) { for (let i = 1; i < chars.length; i++) {
if (chars[i] === '|' && chars[i - 1] !== '\\') { if (chars[ i ] === '|' && chars[ i - 1 ] !== '\\') {
chars[i] = placeholder; chars[ i ] = placeholder;
} }
} }
const lines = chars.join('').split(placeholder).map(line => line.trim()); const lines = chars.join('').split(placeholder).map(line => line.trim());
@ -1463,7 +1487,7 @@ async function executeSlashCommands(text, unescape = false) {
let pipeResult = ''; let pipeResult = '';
for (let index = 0; index < lines.length; index++) { for (let index = 0; index < lines.length; index++) {
const trimmedLine = lines[index].trim(); const trimmedLine = lines[ index ].trim();
if (!trimmedLine.startsWith('/')) { if (!trimmedLine.startsWith('/')) {
continue; continue;
@ -1483,7 +1507,7 @@ async function executeSlashCommands(text, unescape = false) {
let unnamedArg = result.value || pipeResult; let unnamedArg = result.value || pipeResult;
if (typeof result.args === 'object') { if (typeof result.args === 'object') {
for (let [key, value] of Object.entries(result.args)) { for (let [ key, value ] of Object.entries(result.args)) {
if (typeof value === 'string') { if (typeof value === 'string') {
value = substituteParams(value.trim()); value = substituteParams(value.trim());
@ -1491,7 +1515,7 @@ async function executeSlashCommands(text, unescape = false) {
value = value.replace(/{{pipe}}/i, pipeResult || ''); value = value.replace(/{{pipe}}/i, pipeResult || '');
} }
result.args[key] = value; result.args[ key ] = value;
} }
} }
} }
@ -1507,7 +1531,7 @@ async function executeSlashCommands(text, unescape = false) {
} }
if (result.command.purgeFromMessage) { if (result.command.purgeFromMessage) {
linesToRemove.push(lines[index]); linesToRemove.push(lines[ index ]);
} }
} }
@ -1516,7 +1540,7 @@ async function executeSlashCommands(text, unescape = false) {
return { interrupt, newText, pipe: pipeResult }; return { interrupt, newText, pipe: pipeResult };
} }
function setSlashCommandAutocomplete(textarea) { function setSlashCommandAutocomplete (textarea) {
textarea.autocomplete({ textarea.autocomplete({
source: (input, output) => { source: (input, output) => {
// Only show for slash commands and if there's no space // Only show for slash commands and if there's no space
@ -1531,7 +1555,7 @@ function setSlashCommandAutocomplete(textarea) {
.filter(x => x.startsWith(slashCommand)) // Filter by the input .filter(x => x.startsWith(slashCommand)) // Filter by the input
.sort((a, b) => a.localeCompare(b)) // Sort alphabetically .sort((a, b) => a.localeCompare(b)) // Sort alphabetically
// .slice(0, 20) // Limit to 20 results // .slice(0, 20) // Limit to 20 results
.map(x => ({ label: parser.helpStrings[x], value: `/${x} ` })); // Map to the help string .map(x => ({ label: parser.helpStrings[ x ], value: `/${x} ` })); // Map to the help string
output(result); // Return the results output(result); // Return the results
}, },