From 62fd450c592653fd256eaf631372cd05c72745ae Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Tue, 1 Oct 2024 00:06:18 +0200 Subject: [PATCH] Refactor /listinjects, deprecate its "format" arg --- public/scripts/slash-commands.js | 74 +++++++++++-------- .../SlashCommandReturnHelper.js | 16 ++-- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 792e54bf1..17352b233 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -1525,11 +1525,20 @@ export function initDefaultSlashCommands() { name: 'listinjects', callback: listInjectsCallback, helpString: 'Lists all script injections for the current chat. Displays injects in a popup by default. Use the format argument to change the output format.', - returns: 'JSON object of script injections', + returns: 'Optionalls the JSON object of script injections', namedArgumentList: [ + SlashCommandNamedArgument.fromProps({ + name: 'return', + description: 'The way how you want the return value to be provided', + typeList: [ARGUMENT_TYPE.STRING], + defaultValue: 'object', + enumList: slashCommandReturnHelper.enumList({ allowPipe: false, allowObject: true, allowChat: true, allowPopup: true, allowTextVersion: false }), + forceEnum: true, + }), + // TODO remove some day SlashCommandNamedArgument.fromProps({ name: 'format', - description: 'output format', + description: 'DEPRECATED - use "return" instead - output format', typeList: [ARGUMENT_TYPE.STRING], isRequired: true, forceEnum: true, @@ -1798,37 +1807,44 @@ function injectCallback(args, value) { } async function listInjectsCallback(args) { - const type = String(args?.format).toLowerCase().trim(); - if (!chat_metadata.script_injects || !Object.keys(chat_metadata.script_injects).length) { - type !== 'none' && toastr.info('No script injections for the current chat'); - return JSON.stringify({}); + /** @type {import('./slash-commands/SlashCommandReturnHelper.js').SlashCommandReturnType} */ + let returnType = args.return; + + // Old legacy return type handling + if (args.format) { + toastr.warning(`Legacy argument 'format' with value '${args.format}' is deprecated. Please use 'return' instead. Routing to the correct return type...`, 'Deprecation warning'); + const type = String(args?.format).toLowerCase().trim(); + if (!chat_metadata.script_injects || !Object.keys(chat_metadata.script_injects).length) { + type !== 'none' && toastr.info('No script injections for the current chat'); + } + switch (type) { + case 'none': + returnType = 'none'; + break; + case 'chat': + returnType = 'chat-html'; + break; + case 'popup': + default: + returnType = 'popup-html'; + break; + } } - const injects = Object.entries(chat_metadata.script_injects) - .map(([id, inject]) => { - const position = Object.entries(extension_prompt_types); - const positionName = position.find(([_, value]) => value === inject.position)?.[0] ?? 'unknown'; - return `* **${id}**: ${inject.value} (${positionName}, depth: ${inject.depth}, scan: ${inject.scan ?? false}, role: ${inject.role ?? extension_prompt_roles.SYSTEM})`; - }) - .join('\n'); + // Now the actual new return type handling - const converter = new showdown.Converter(); - const messageText = `### Script injections:\n${injects}`; - const htmlMessage = DOMPurify.sanitize(converter.makeHtml(messageText)); + const buildTextValue = (injects) => { + const injectsStr = Object.entries(injects) + .map(([id, inject]) => { + const position = Object.entries(extension_prompt_types); + const positionName = position.find(([_, value]) => value === inject.position)?.[0] ?? 'unknown'; + return `* **${id}**: ${inject.value} (${positionName}, depth: ${inject.depth}, scan: ${inject.scan ?? false}, role: ${inject.role ?? extension_prompt_roles.SYSTEM})`; + }) + .join('\n'); + return `### Script injections:\n${injectsStr}`; + }; - switch (type) { - case 'none': - break; - case 'chat': - sendSystemMessage(system_message_types.GENERIC, htmlMessage); - break; - case 'popup': - default: - await callGenericPopup(htmlMessage, POPUP_TYPE.TEXT); - break; - } - - return JSON.stringify(chat_metadata.script_injects); + return await slashCommandReturnHelper.doReturn(returnType ?? 'object', chat_metadata.script_injects, { objectToStringFunc: buildTextValue }); } /** diff --git a/public/scripts/slash-commands/SlashCommandReturnHelper.js b/public/scripts/slash-commands/SlashCommandReturnHelper.js index 90ec0d783..cdcc914cd 100644 --- a/public/scripts/slash-commands/SlashCommandReturnHelper.js +++ b/public/scripts/slash-commands/SlashCommandReturnHelper.js @@ -7,6 +7,9 @@ import { enumTypes, SlashCommandEnumValue } from './SlashCommandEnumValue.js'; /** @typedef {'pipe'|'object'|'chat-html'|'chat-text'|'popup-html'|'popup-text'|'toast-html'|'toast-text'|'console'|'none'} SlashCommandReturnType */ export const slashCommandReturnHelper = { + // Without this, VSCode formatter fucks up JS docs. Don't ask me why. + _: false, + /** * Gets/creates the enum list of types of return relevant for a slash command * @@ -15,18 +18,19 @@ export const slashCommandReturnHelper = { * @param {boolean} [options.allowObject=false] Allow option to return the value as an object * @param {boolean} [options.allowChat=false] Allow option to return the value as a chat message * @param {boolean} [options.allowPopup=false] Allow option to return the value as a popup + * @param {boolean}[options.allowTextVersion=true] Used in combination with chat/popup/toast, some of them do not make sense for text versions, e.g.if you are building a HTML string anyway * @returns {SlashCommandEnumValue[]} The enum list */ - enumList: ({ allowPipe = true, allowObject = false, allowChat = false, allowPopup = false } = {}) => [ + enumList: ({ allowPipe = true, allowObject = false, allowChat = false, allowPopup = false, allowTextVersion = true } = {}) => [ allowPipe && new SlashCommandEnumValue('pipe', 'Return to the pipe for the next command', enumTypes.name, '|'), allowObject && new SlashCommandEnumValue('object', 'Return as an object to the pipe for the next command', enumTypes.variable, enumIcons.dictionary), allowChat && new SlashCommandEnumValue('chat-html', 'Sending a chat message with the return value - Can display HTML', enumTypes.command, enumIcons.message), - allowChat && new SlashCommandEnumValue('chat-text', 'Sending a chat message with the return value - Will only display as text', enumTypes.qr, enumIcons.message), - new SlashCommandEnumValue('popup-html', 'Showing as a popup with the return value - Can display HTML', enumTypes.command, enumIcons.popup), - new SlashCommandEnumValue('popup-text', 'Showing as a popup with the return value - Will only display as text', enumTypes.qr, enumIcons.popup), + allowChat && allowTextVersion && new SlashCommandEnumValue('chat-text', 'Sending a chat message with the return value - Will only display as text', enumTypes.qr, enumIcons.message), + allowPopup && new SlashCommandEnumValue('popup-html', 'Showing as a popup with the return value - Can display HTML', enumTypes.command, enumIcons.popup), + allowPopup && allowTextVersion && new SlashCommandEnumValue('popup-text', 'Showing as a popup with the return value - Will only display as text', enumTypes.qr, enumIcons.popup), new SlashCommandEnumValue('toast-html', 'Show the return value as a toast notification - Can display HTML', enumTypes.command, 'ℹ️'), - new SlashCommandEnumValue('toast-text', 'Show the return value as a toast notification - Will only display as text', enumTypes.qr, 'ℹ️'), - new SlashCommandEnumValue('console', 'Log the return value to the console', enumTypes.enum, '>'), + allowTextVersion && new SlashCommandEnumValue('toast-text', 'Show the return value as a toast notification - Will only display as text', enumTypes.qr, 'ℹ️'), + new SlashCommandEnumValue('console', 'Log the return value (object, if it can be one) to the console', enumTypes.enum, '>'), new SlashCommandEnumValue('none', 'No return value'), ].filter(x => !!x),