Add message-role command

1f0c0ccff4bf4fcec6a9685546bb86d5df25e87f

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

2 files changed, +97 -1Ignore whitespace
public/scripts/slash-commands.js+91 -1
@@ -766,6 +766,48 @@ export function initDefaultSlashCommands() {
766766 `,
767767 }));
768768 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
769+ name: 'message-role',
770+ callback: messageRoleCallback,
771+ returns: 'The role of the message sender',
772+ namedArgumentList: [
773+ SlashCommandNamedArgument.fromProps({
774+ name: 'at',
775+ description: 'the ID of the message to modify (index-based, corresponding to message id). If omitted, the last message is chosen.\nNegative values are accepted and will work similarly to how \'depth\' usually works. For example, -1 will modify the message right before the last message in chat. At must be nonzero.',
776+ typeList: [ARGUMENT_TYPE.NUMBER],
777+ defaultValue: '',
778+ enumProvider: commonEnumProviders.messages({ allowIdAfter: true }),
779+ }),
780+ ],
781+ unnamedArgumentList: [
782+ SlashCommandArgument.fromProps({
783+ description: 'Role to set for the message sender (user, assistant, system)',
784+ typeList: [ARGUMENT_TYPE.STRING],
785+ isRequired: false,
786+ enumProvider: commonEnumProviders.messageRoles,
787+ }),
788+ ],
789+ helpString: `
790+ <div>
791+ Changes the role of a message sender to one of your choice.
792+ If no role is provided, just gets the current role of the message sender.
793+ If no index is provided, the last message is chosen.
794+ </div>
795+ <div>
796+ <strong>Example:</strong>
797+ <ul>
798+ <li>
799+ <pre><code>/message-role | /echo</code></pre>
800+ Will output the role of the sender of the last message.
801+ </li>
802+ <li>
803+ <pre><code>/message-role at=-2 assistant</code></pre>
804+ Will change the third message from the bottom to be sent by the assistant.
805+ </li>
806+ </ul>
807+ </div>
808+ `,
809+ }));
810+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
769811 name: 'message-name',
770812 callback: messageNameCallback,
771813 returns: 'The name of the message sender',
@@ -4562,13 +4604,61 @@ export function getNameAndAvatarForMessage(character, name = null) {
45624604}
45634605
45644606/**
4607+ * Changes the character role on a message at a given index.
4608+ * @param {object?} args - Named arguments
4609+ * @param {string} role - Role to change to.
4610+ *
4611+ * @returns {Promise<string>} The updated message role.
4612+ */
4613+async function messageRoleCallback(args, role) {
4614+ let modifyAt = Number(args?.at ?? (chat.length - 1));
4615+ // Convert possible depth parameter to index
4616+ if (!isNaN(modifyAt) && (modifyAt < 0 || Object.is(modifyAt, -0))) {
4617+ // Negative value means going back from current chat length. (E.g.: 8 messages, Depth 1 means insert at index 7)
4618+ modifyAt = chat.length + modifyAt;
4619+ }
4620+
4621+ const message = chat[modifyAt];
4622+ if (!message) {
4623+ toastr.warning(t`No message found at the specified index.`);
4624+ return '';
4625+ }
4626+
4627+ role = String(role ?? '').trim().toLowerCase();
4628+ if (!role || !['user', 'assistant', 'system'].includes(role)) {
4629+ return message?.extra?.type === system_message_types.NARRATOR
4630+ ? 'system'
4631+ : message.is_user ? 'user' : 'assistant';
4632+ }
4633+
4634+ message.extra = message.extra || {};
4635+ if (role === 'system') {
4636+ message.extra.type = system_message_types.NARRATOR;
4637+ } else {
4638+ delete message.extra.type;
4639+ }
4640+ message.is_user = role === 'user';
4641+
4642+ await eventSource.emit(event_types.MESSAGE_EDITED, modifyAt);
4643+ const existingMessage = chatElement.find(`.mes[mesid="${modifyAt}"]`);
4644+ if (existingMessage.length) {
4645+ addOneMessage(message, { forceId: modifyAt, insertAfter: modifyAt, scroll: false });
4646+ existingMessage.remove();
4647+ }
4648+ await eventSource.emit(event_types.MESSAGE_UPDATED, modifyAt);
4649+ await saveChatConditional();
4650+
4651+ return role;
4652+}
4653+
4654+/**
45654655 * Changes the character name on a message at a given index.
45664656 * @param {object?} args - Named arguments
45674657 * @param {string} name - Name to change to.
45684658 *
45694659 * @returns {Promise<string>} The updated message name.
45704660 */
45714661export async function messageNameCallback(args, name) {
45724662 let modifyAt = Number(args?.at ?? (chat.length - 1));
45734663 // Convert possible depth parameter to index
45744664 if (!isNaN(modifyAt) && (modifyAt < 0 || Object.is(modifyAt, -0))) {
public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js+6 -0
@@ -329,4 +329,10 @@ export const commonEnumProviders = {
329329 new SlashCommandEnumValue('null', null, enumTypes.type, enumIcons.null),
330330 new SlashCommandEnumValue('undefined', null, enumTypes.type, enumIcons.undefined),
331331 ],
332+
333+ messageRoles: () => [
334+ new SlashCommandEnumValue('user', null, enumTypes.enum, enumIcons.user),
335+ new SlashCommandEnumValue('assistant', null, enumTypes.enum, enumIcons.assistant),
336+ new SlashCommandEnumValue('system', null, enumTypes.enum, enumIcons.system),
337+ ],
332338};