Add message-role command
| @@ -766,6 +766,48 @@ export function initDefaultSlashCommands() { | ||
| 766 | 766 | `, |
| 767 | 767 | })); |
| 768 | 768 | 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({ | |
| 769 | 811 | name: 'message-name', |
| 770 | 812 | callback: messageNameCallback, |
| 771 | 813 | returns: 'The name of the message sender', |
| @@ -4562,13 +4604,61 @@ export function getNameAndAvatarForMessage(character, name = null) { | ||
| 4562 | 4604 | } |
| 4563 | 4605 | |
| 4564 | 4606 | /** |
| 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 | +/** | |
| 4565 | 4655 | * Changes the character name on a message at a given index. |
| 4566 | 4656 | * @param {object?} args - Named arguments |
| 4567 | 4657 | * @param {string} name - Name to change to. |
| 4568 | 4658 | * |
| 4569 | 4659 | * @returns {Promise<string>} The updated message name. |
| 4570 | 4660 | */ |
| 4571 | 4661 | export async function messageNameCallback(args, name) { |
| 4572 | 4662 | let modifyAt = Number(args?.at ?? (chat.length - 1)); |
| 4573 | 4663 | // Convert possible depth parameter to index |
| 4574 | 4664 | if (!isNaN(modifyAt) && (modifyAt < 0 || Object.is(modifyAt, -0))) { |
| @@ -329,4 +329,10 @@ export const commonEnumProviders = { | ||
| 329 | 329 | new SlashCommandEnumValue('null', null, enumTypes.type, enumIcons.null), |
| 330 | 330 | new SlashCommandEnumValue('undefined', null, enumTypes.type, enumIcons.undefined), |
| 331 | 331 | ], |
| 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 | + ], | |
| 332 | 338 | }; |